mirror of
https://github.com/LGUG2Z/komorebi.git
synced 2026-03-29 13:41:56 +02:00
refactor(komorebic): update clap, add cli docs
The latest clap beta introduced a lot of breaking changes for komorebic, so I decided it was a good time to refactor a little and add documentation to all of the cli commands. The primary change for komorebic is that subcommands now only take structs as arguments, so every enum must be wrapped in a struct. Some macros have been introduced to ease this. Using on|off alongside enable|disable for BooleanState arguments has been deprecated, going forward only enable|disable will be supported. The commands to introduce float rules have been refactored to make use of ApplicationTarget, and a single command 'float-rule' has been introduced in the cli. Finally I took some time to standardise the sample AHK config a little, primarily making sure that command prompt windows are never shown for any of the configuration commands. BREAKING CHANGE: float-exe, float-class, and float-title have been deprecated in favour of float-rule in komorebic. workspace-tiling now only accepts enable|disable as valid inputs to the final arg, deprecating the previously also valid on|off. re #8
This commit is contained in:
22
Cargo.lock
generated
22
Cargo.lock
generated
@@ -67,9 +67,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "1.3.1"
|
||||
version = "1.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2da1976d75adbe5fbc88130ecd119529cf1cc6a93ae1546d8696ee66f0d21af1"
|
||||
checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
@@ -104,9 +104,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "3.0.0-beta.2"
|
||||
version = "3.0.0-beta.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4bd1061998a501ee7d4b6d449020df3266ca3124b941ec56cf2005c3779ca142"
|
||||
checksum = "fcd70aa5597dbc42f7217a543f9ef2768b2ef823ba29036072d30e1d88e98406"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"bitflags",
|
||||
@@ -117,15 +117,14 @@ dependencies = [
|
||||
"strsim",
|
||||
"termcolor",
|
||||
"textwrap",
|
||||
"unicode-width",
|
||||
"vec_map",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "3.0.0-beta.2"
|
||||
version = "3.0.0-beta.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "370f715b81112975b1b69db93e0b56ea4cd4e5002ac43b2da8474106a54096a1"
|
||||
checksum = "0b5bb0d655624a0b8770d1c178fb8ffcb1f91cc722cb08f451e3dc72465421ac"
|
||||
dependencies = [
|
||||
"heck",
|
||||
"proc-macro-error",
|
||||
@@ -490,6 +489,7 @@ dependencies = [
|
||||
"color-eyre",
|
||||
"dirs",
|
||||
"komorebi-core",
|
||||
"paste",
|
||||
"powershell_script",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -706,9 +706,9 @@ checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56"
|
||||
|
||||
[[package]]
|
||||
name = "os_str_bytes"
|
||||
version = "2.4.0"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "afb2e1c3ee07430c2cf76151675e583e0f19985fa6efae47d6848a3e2c824f85"
|
||||
checksum = "6acbef58a60fe69ab50510a55bc8cdd4d6cf2283d27ad338f54cb52747a9cf2d"
|
||||
|
||||
[[package]]
|
||||
name = "owo-colors"
|
||||
@@ -1089,9 +1089,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "textwrap"
|
||||
version = "0.12.1"
|
||||
version = "0.14.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "203008d98caf094106cfaba70acfed15e18ed3ddb7d94e49baec153a2b462789"
|
||||
checksum = "0066c8d12af8b5acd21e00547c3797fde4e8677254a7ee429176ccebbe93dd80"
|
||||
dependencies = [
|
||||
"unicode-width",
|
||||
]
|
||||
|
||||
10
README.md
10
README.md
@@ -88,9 +88,9 @@ If you have AutoHotKey installed and a `komorebi.ahk` file in your home director
|
||||
PowerShell prompt to find your home directory), `komorebi` will automatically try to load it when starting.
|
||||
|
||||
If you are experiencing behaviour where
|
||||
[closing a window leaves a blank tile, but minimizing the same window does not](https://github.com/LGUG2Z/komorebi/issues/6),
|
||||
you have probably enabled a 'close/minimize to tray' option for that application. You can tell _komorebi_ to handle this
|
||||
application appropriately by identifying it via the executable name or the window class:
|
||||
[closing a window leaves a blank tile, but minimizing the same window does not](https://github.com/LGUG2Z/komorebi/issues/6)
|
||||
, you have probably enabled a 'close/minimize to tray' option for that application. You can tell _komorebi_ to handle
|
||||
this application appropriately by identifying it via the executable name or the window class:
|
||||
|
||||
```powershell
|
||||
komorebic.exe identify-tray-application exe Discord.exe
|
||||
@@ -103,6 +103,10 @@ As previously mentioned, this project does not handle anything related to keybin
|
||||
personally use AutoHotKey to manage my window management shortcuts, and have provided a
|
||||
sample [komorebi.ahk](komorebi.sample.ahk) AHK script that you can use as a starting point for your own.
|
||||
|
||||
You can run `komorebic.exe` to get a full list of the commands that you can use to customise `komorebi` and create
|
||||
keybindings with. You can run `komorebic.exe <COMMAND> --help` to get a full explanation of the arguments required for
|
||||
each command.
|
||||
|
||||
## Features
|
||||
|
||||
- [x] Multi-monitor
|
||||
|
||||
@@ -18,7 +18,8 @@ fn main() {
|
||||
Windows::Win32::System::Threading::AttachThreadInput,
|
||||
Windows::Win32::System::Threading::GetCurrentProcessId,
|
||||
Windows::Win32::UI::KeyboardAndMouseInput::SetFocus,
|
||||
Windows::Win32::UI::Accessibility::{SetWinEventHook, HWINEVENTHOOK},
|
||||
Windows::Win32::UI::Accessibility::SetWinEventHook,
|
||||
Windows::Win32::UI::Accessibility::HWINEVENTHOOK,
|
||||
// error: `Windows.Win32.UI.WindowsAndMessaging.GWL_EXSTYLE` not found in metadata
|
||||
Windows::Win32::UI::WindowsAndMessaging::*,
|
||||
);
|
||||
|
||||
@@ -8,7 +8,7 @@ edition = "2018"
|
||||
[dependencies]
|
||||
bindings = { package = "bindings", path = "../bindings" }
|
||||
|
||||
clap = "3.0.0-beta.2"
|
||||
clap = "3.0.0-beta.4"
|
||||
color-eyre = "0.5"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
use clap::Clap;
|
||||
use clap::ArgEnum;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use strum::Display;
|
||||
use strum::EnumString;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString)]
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
#[derive(Clap)]
|
||||
pub enum CycleDirection {
|
||||
Previous,
|
||||
Next,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::num::NonZeroUsize;
|
||||
|
||||
use clap::Clap;
|
||||
use clap::ArgEnum;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use strum::Display;
|
||||
@@ -10,18 +10,16 @@ use crate::OperationDirection;
|
||||
use crate::Rect;
|
||||
use crate::Sizing;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString)]
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
#[derive(Clap)]
|
||||
pub enum Layout {
|
||||
BSP,
|
||||
Columns,
|
||||
Rows,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString)]
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
#[derive(Clap)]
|
||||
pub enum LayoutFlip {
|
||||
Horizontal,
|
||||
Vertical,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::str::FromStr;
|
||||
|
||||
use clap::Clap;
|
||||
use clap::ArgEnum;
|
||||
use color_eyre::Result;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
@@ -80,16 +80,16 @@ impl FromStr for SocketMessage {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Display, EnumString)]
|
||||
#[derive(Clone, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
pub enum ApplicationIdentifier {
|
||||
Exe,
|
||||
Class,
|
||||
Title,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString)]
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
#[derive(Clap)]
|
||||
pub enum Sizing {
|
||||
Increase,
|
||||
Decrease,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use clap::Clap;
|
||||
use clap::ArgEnum;
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use strum::Display;
|
||||
@@ -7,9 +7,8 @@ use strum::EnumString;
|
||||
use crate::Layout;
|
||||
use crate::LayoutFlip;
|
||||
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString)]
|
||||
#[derive(Clone, Copy, Debug, Serialize, Deserialize, Display, EnumString, ArgEnum)]
|
||||
#[strum(serialize_all = "snake_case")]
|
||||
#[derive(Clap)]
|
||||
pub enum OperationDirection {
|
||||
Left,
|
||||
Right,
|
||||
|
||||
@@ -1,50 +1,49 @@
|
||||
#SingleInstance Force
|
||||
|
||||
; Enable hot reloading of changes to this file
|
||||
Run, komorebic.exe watch-configuration enable
|
||||
Run, komorebic.exe watch-configuration enable, , Hide
|
||||
|
||||
; Enable focus follows mouse
|
||||
Run, komorebic.exe focus-follows-mouse enable
|
||||
Run, komorebic.exe focus-follows-mouse enable, , Hide
|
||||
|
||||
; Ensure there are 3 workspaces created on monitor 0
|
||||
Run, komorebic.exe ensure-workspaces 0 5
|
||||
Run, komorebic.exe ensure-workspaces 0 5, , Hide
|
||||
|
||||
; Give the workspaces some optional names
|
||||
Run, komorebic.exe workspace-name 0 0 bsp
|
||||
Run, komorebic.exe workspace-name 0 1 columns
|
||||
Run, komorebic.exe workspace-name 0 2 thicc
|
||||
Run, komorebic.exe workspace-name 0 3 matrix
|
||||
Run, komorebic.exe workspace-name 0 4 floaty
|
||||
Run, komorebic.exe workspace-name 0 0 bsp, , Hide
|
||||
Run, komorebic.exe workspace-name 0 1 columns, , Hide
|
||||
Run, komorebic.exe workspace-name 0 2 thicc, , Hide
|
||||
Run, komorebic.exe workspace-name 0 3 matrix, , Hide
|
||||
Run, komorebic.exe workspace-name 0 4 floaty, , Hide
|
||||
|
||||
; Set the padding of the different workspaces
|
||||
Run, komorebic.exe workspace-padding 0 1 30
|
||||
Run, komorebic.exe container-padding 0 1 30
|
||||
Run, komorebic.exe workspace-padding 0 2 200
|
||||
Run, komorebic.exe workspace-padding 0 3 0
|
||||
Run, komorebic.exe container-padding 0 3 0
|
||||
Run, komorebic.exe workspace-padding 0 1 30, , Hide
|
||||
Run, komorebic.exe container-padding 0 1 30, , Hide
|
||||
Run, komorebic.exe workspace-padding 0 2 200, , Hide
|
||||
Run, komorebic.exe workspace-padding 0 3 0, , Hide
|
||||
Run, komorebic.exe container-padding 0 3 0, , Hide
|
||||
|
||||
; Set the layouts of different workspaces
|
||||
Run, komorebic.exe workspace-layout 0 1 columns
|
||||
Run, komorebic.exe workspace-layout 0 1 columns, , Hide
|
||||
|
||||
; Set the floaty layout to not tile any windows
|
||||
Run, komorebic.exe workspace-tiling 0 4 off
|
||||
Run, komorebic.exe workspace-tiling 0 4 disable, , Hide
|
||||
|
||||
; Always float IntelliJ popups, matching on class
|
||||
Run, komorebic.exe float-class SunAwtDialog, , Hide
|
||||
Run, komorebic.exe float-rule class SunAwtDialog, , Hide
|
||||
; Always float Control Panel, matching on title
|
||||
Run, komorebic.exe float-title "Control Panel", , Hide
|
||||
Run, komorebic.exe float-rule title "Control Panel", , Hide
|
||||
; Always float Task Manager, matching on class
|
||||
Run, komorebic.exe float-class TaskManagerWindow, , Hide
|
||||
Run, komorebic.exe float-rule class TaskManagerWindow, , Hide
|
||||
; Always float Wally, matching on executable name
|
||||
Run, komorebic.exe float-exe Wally.exe, , Hide
|
||||
Run, komorebic.exe float-exe wincompose.exe, , Hide
|
||||
Run, komorebic.exe float-rule exe Wally.exe, , Hide
|
||||
Run, komorebic.exe float-rule exe wincompose.exe, , Hide
|
||||
; Always float Calculator app, matching on window title
|
||||
Run, komorebic.exe float-title Calculator, , Hide
|
||||
Run, komorebic.exe float-exe 1Password.exe, , Hide
|
||||
Run, komorebic.exe float-rule title Calculator, , Hide
|
||||
Run, komorebic.exe float-rule exe 1Password.exe, , Hide
|
||||
|
||||
; Identify applications that close to the tray
|
||||
Run, komorebic.exe identify-tray-application exe Discord.exe, , Hide
|
||||
Run, komorebic.exe identify-tray-application exe Telegram.exe, , Hide
|
||||
|
||||
; Change the focused window, Alt + Vim direction keys
|
||||
!h::
|
||||
@@ -65,36 +64,36 @@ return
|
||||
|
||||
; Move the focused window in a given direction, Alt + Shift + Vim direction keys
|
||||
!+h::
|
||||
Run, komorebic.exe move left, Hide
|
||||
Run, komorebic.exe move left, , Hide
|
||||
return
|
||||
|
||||
!+j::
|
||||
Run, komorebic.exe move down, Hide
|
||||
Run, komorebic.exe move down, , Hide
|
||||
return
|
||||
|
||||
!+k::
|
||||
Run, komorebic.exe move up, Hide
|
||||
Run, komorebic.exe move up, , Hide
|
||||
return
|
||||
|
||||
!+l::
|
||||
Run, komorebic.exe move right, Hide
|
||||
Run, komorebic.exe move right, , Hide
|
||||
return
|
||||
|
||||
; Stack the focused window in a given direction, Alt + Shift + direction keys
|
||||
!+Left::
|
||||
Run, komorebic.exe stack left, Hide
|
||||
Run, komorebic.exe stack left, , Hide
|
||||
return
|
||||
|
||||
!+Down::
|
||||
Run, komorebic.exe stack down, Hide
|
||||
Run, komorebic.exe stack down, , Hide
|
||||
return
|
||||
|
||||
!+Up::
|
||||
Run, komorebic.exe stack up, Hide
|
||||
Run, komorebic.exe stack up, , Hide
|
||||
return
|
||||
|
||||
!+Right::
|
||||
Run, komorebic.exe stack right, Hide
|
||||
Run, komorebic.exe stack right, , Hide
|
||||
return
|
||||
|
||||
!]::
|
||||
@@ -107,102 +106,102 @@ return
|
||||
|
||||
; Unstack the focused window, Alt + Shift + D
|
||||
!+d::
|
||||
Run, komorebic.exe unstack, Hide
|
||||
Run, komorebic.exe unstack, , Hide
|
||||
return
|
||||
|
||||
; Promote the focused window to the top of the tree, Alt + Shift + Enter
|
||||
!+Enter::
|
||||
Run, komorebic.exe promote, Hide
|
||||
Run, komorebic.exe promote, , Hide
|
||||
return
|
||||
|
||||
; Switch to an equal-width, max-height column layout on the main workspace, Alt + Shift + C
|
||||
!+c::
|
||||
Run, komorebic.exe workspace-layout 0 0 columns, Hide
|
||||
Run, komorebic.exe workspace-layout 0 0 columns, , Hide
|
||||
return
|
||||
|
||||
; Switch to the default bsp tiling layout on the main workspace, Alt + Shift + T
|
||||
!+t::
|
||||
Run, komorebic.exe workspace-layout 0 0 bsp, Hide
|
||||
Run, komorebic.exe workspace-layout 0 0 bsp, , Hide
|
||||
return
|
||||
|
||||
; Toggle the Monocle layout for the focused window, Alt + Shift + F
|
||||
!+f::
|
||||
Run, komorebic.exe toggle-monocle, Hide
|
||||
Run, komorebic.exe toggle-monocle, , Hide
|
||||
return
|
||||
|
||||
; Flip horizontally, Alt + X
|
||||
!x::
|
||||
Run, komorebic.exe flip-layout horizontal, Hide
|
||||
Run, komorebic.exe flip-layout horizontal, , Hide
|
||||
return
|
||||
|
||||
; Flip vertically, Alt + Y
|
||||
!y::
|
||||
Run, komorebic.exe flip-layout vertical, Hide
|
||||
Run, komorebic.exe flip-layout vertical, , Hide
|
||||
return
|
||||
|
||||
; Force a retile if things get janky, Alt + Shift + R
|
||||
!+r::
|
||||
Run, komorebic.exe retile, Hide
|
||||
Run, komorebic.exe retile, , Hide
|
||||
return
|
||||
|
||||
; Float the focused window, Alt + T
|
||||
!t::
|
||||
Run, komorebic.exe toggle-float, Hide
|
||||
Run, komorebic.exe toggle-float, , Hide
|
||||
return
|
||||
|
||||
; Reload ~/komorebi.ahk, Alt + O
|
||||
!o::
|
||||
Run, komorebic.exe reload-configuration, Hide
|
||||
Run, komorebic.exe reload-configuration, , Hide
|
||||
return
|
||||
|
||||
; Pause responding to any window events or komorebic commands, Alt + P
|
||||
!p::
|
||||
Run, komorebic.exe toggle-pause, Hide
|
||||
Run, komorebic.exe toggle-pause, , Hide
|
||||
return
|
||||
|
||||
; Switch to workspace
|
||||
!1::
|
||||
Send !
|
||||
Run, komorebic.exe focus-workspace 0, Hide
|
||||
Run, komorebic.exe focus-workspace 0, , Hide
|
||||
return
|
||||
|
||||
!2::
|
||||
Send !
|
||||
Run, komorebic.exe focus-workspace 1, Hide
|
||||
Run, komorebic.exe focus-workspace 1, , Hide
|
||||
return
|
||||
|
||||
!3::
|
||||
Send !
|
||||
Run, komorebic.exe focus-workspace 2, Hide
|
||||
Run, komorebic.exe focus-workspace 2, , Hide
|
||||
return
|
||||
|
||||
!4::
|
||||
Send !
|
||||
Run, komorebic.exe focus-workspace 3, Hide
|
||||
Run, komorebic.exe focus-workspace 3, , Hide
|
||||
return
|
||||
|
||||
!5::
|
||||
Send !
|
||||
Run, komorebic.exe focus-workspace 4, Hide
|
||||
Run, komorebic.exe focus-workspace 4, , Hide
|
||||
return
|
||||
|
||||
; Move window to workspace
|
||||
!+1::
|
||||
Run, komorebic.exe move-to-workspace 0, Hide
|
||||
Run, komorebic.exe move-to-workspace 0, , Hide
|
||||
return
|
||||
|
||||
!+2::
|
||||
Run, komorebic.exe move-to-workspace 1, Hide
|
||||
Run, komorebic.exe move-to-workspace 1, , Hide
|
||||
return
|
||||
|
||||
!+3::
|
||||
Run, komorebic.exe move-to-workspace 2, Hide
|
||||
Run, komorebic.exe move-to-workspace 2, , Hide
|
||||
return
|
||||
|
||||
!+4::
|
||||
Run, komorebic.exe move-to-workspace 3, Hide
|
||||
Run, komorebic.exe move-to-workspace 3, , Hide
|
||||
return
|
||||
|
||||
!+5::
|
||||
Run, komorebic.exe move-to-workspace 4, Hide
|
||||
Run, komorebic.exe move-to-workspace 4, , Hide
|
||||
return
|
||||
|
||||
@@ -193,6 +193,7 @@ impl WindowManager {
|
||||
classes.push(id);
|
||||
}
|
||||
}
|
||||
ApplicationIdentifier::Title => {}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -9,9 +9,10 @@ edition = "2018"
|
||||
bindings = { package = "bindings", path = "../bindings" }
|
||||
komorebi-core = { path = "../komorebi-core" }
|
||||
|
||||
clap = "3.0.0-beta.2"
|
||||
clap = "3.0.0-beta.4"
|
||||
color-eyre = "0.5"
|
||||
dirs = "3"
|
||||
paste = "1"
|
||||
powershell_script = "0.2"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
|
||||
@@ -4,6 +4,8 @@ use std::io::BufReader;
|
||||
use std::io::ErrorKind;
|
||||
use std::io::Write;
|
||||
|
||||
use clap::AppSettings;
|
||||
use clap::ArgEnum;
|
||||
use clap::Clap;
|
||||
use color_eyre::eyre::ContextCompat;
|
||||
use color_eyre::Result;
|
||||
@@ -22,8 +24,129 @@ use komorebi_core::OperationDirection;
|
||||
use komorebi_core::Sizing;
|
||||
use komorebi_core::SocketMessage;
|
||||
|
||||
#[derive(ArgEnum)]
|
||||
enum BooleanState {
|
||||
Enable,
|
||||
Disable,
|
||||
}
|
||||
|
||||
impl From<BooleanState> for bool {
|
||||
fn from(b: BooleanState) -> Self {
|
||||
match b {
|
||||
BooleanState::Enable => true,
|
||||
BooleanState::Disable => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! gen_enum_subcommand {
|
||||
($name:ident, $element:ty) => {
|
||||
paste::paste! {
|
||||
#[derive(clap::Clap)]
|
||||
pub struct $name {
|
||||
#[clap(arg_enum)]
|
||||
[<$element:snake>]: $element
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
gen_enum_subcommand!(Focus, OperationDirection);
|
||||
gen_enum_subcommand!(Move, OperationDirection);
|
||||
gen_enum_subcommand!(Stack, OperationDirection);
|
||||
gen_enum_subcommand!(CycleStack, CycleDirection);
|
||||
gen_enum_subcommand!(WatchConfiguration, BooleanState);
|
||||
gen_enum_subcommand!(FlipLayout, LayoutFlip);
|
||||
gen_enum_subcommand!(FocusFollowsMouse, BooleanState);
|
||||
|
||||
macro_rules! gen_target_subcommands {
|
||||
( $( $name:ident ),+ ) => {
|
||||
$(
|
||||
#[derive(clap::Clap)]
|
||||
pub struct $name {
|
||||
target: usize,
|
||||
}
|
||||
)+
|
||||
};
|
||||
}
|
||||
|
||||
gen_target_subcommands!(MoveToMonitor, MoveToWorkspace, FocusMonitor, FocusWorkspace);
|
||||
|
||||
#[derive(Clap)]
|
||||
#[clap(version = "1.0", author = "Jade Iqbal <jadeiqbal@fastmail.com>")]
|
||||
struct Resize {
|
||||
#[clap(arg_enum)]
|
||||
edge: OperationDirection,
|
||||
#[clap(arg_enum)]
|
||||
sizing: Sizing,
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
struct EnsureWorkspaces {
|
||||
/// Monitor index (zero-indexed, ie. the primary/first monitor is 0)
|
||||
monitor: usize,
|
||||
/// Number of desired workspaces
|
||||
workspace_count: usize,
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
struct SizeForMonitorWorkspace {
|
||||
/// Monitor index (zero-indexed, ie. the primary/first monitor is 0)
|
||||
monitor: usize,
|
||||
/// Workspace index on the specified monitor (zero-indexed, ie. the first workspace is 0)
|
||||
workspace: usize,
|
||||
/// Pixels to pad with as an integer
|
||||
size: i32,
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
struct WorkspaceName {
|
||||
/// Monitor index (zero-indexed, ie. the primary/first monitor is 0)
|
||||
monitor: usize,
|
||||
/// Workspace index on the specified monitor (zero-indexed, ie. the first workspace is 0)
|
||||
workspace: usize,
|
||||
/// Name of the workspace as a string
|
||||
value: String,
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
struct WorkspaceLayout {
|
||||
/// Monitor index (zero-indexed, ie. the primary/first monitor is 0)
|
||||
monitor: usize,
|
||||
/// Workspace index on the specified monitor (zero-indexed, ie. the first workspace is 0)
|
||||
workspace: usize,
|
||||
#[clap(arg_enum)]
|
||||
layout: Layout,
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
struct WorkspaceTiling {
|
||||
/// Monitor index (zero-indexed, ie. the primary/first monitor is 0)
|
||||
monitor: usize,
|
||||
/// Workspace index on the specified monitor (zero-indexed, ie. the first workspace is 0)
|
||||
workspace: usize,
|
||||
#[clap(arg_enum)]
|
||||
tile: BooleanState,
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
struct ApplicationTarget {
|
||||
#[clap(arg_enum)]
|
||||
identifier: ApplicationIdentifier,
|
||||
/// Identifier as a string
|
||||
id: String,
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
struct PaddingAdjustment {
|
||||
#[clap(arg_enum)]
|
||||
sizing: Sizing,
|
||||
/// Pixels to adjust by as an integer
|
||||
adjustment: i32,
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
#[clap(version = "0.1.0", author = "Jade Iqbal <jadeiqbal@fastmail.com>")]
|
||||
#[clap(setting = AppSettings::DeriveDisplayOrder)]
|
||||
struct Opts {
|
||||
#[clap(subcommand)]
|
||||
subcmd: SubCommand,
|
||||
@@ -31,123 +154,96 @@ struct Opts {
|
||||
|
||||
#[derive(Clap)]
|
||||
enum SubCommand {
|
||||
Focus(OperationDirection),
|
||||
Move(OperationDirection),
|
||||
Stack(OperationDirection),
|
||||
Resize(Resize),
|
||||
Unstack,
|
||||
CycleStack(CycleDirection),
|
||||
MoveToMonitor(Target),
|
||||
MoveToWorkspace(Target),
|
||||
FocusMonitor(Target),
|
||||
FocusWorkspace(Target),
|
||||
NewWorkspace,
|
||||
Promote,
|
||||
EnsureWorkspaces(WorkspaceCountForMonitor),
|
||||
Retile,
|
||||
ContainerPadding(SizeForMonitorWorkspace),
|
||||
WorkspacePadding(SizeForMonitorWorkspace),
|
||||
WorkspaceLayout(LayoutForMonitorWorkspace),
|
||||
WorkspaceTiling(TilingForMonitorWorkspace),
|
||||
WorkspaceName(NameForMonitorWorkspace),
|
||||
ToggleTiling,
|
||||
ToggleFloat,
|
||||
TogglePause,
|
||||
ToggleMonocle,
|
||||
RestoreWindows,
|
||||
ReloadConfiguration,
|
||||
WatchConfiguration(BooleanState),
|
||||
State,
|
||||
/// Start komorebi.exe as a background process
|
||||
Start,
|
||||
/// Stop the komorebi.exe process and restore all hidden windows
|
||||
Stop,
|
||||
FloatClass(FloatTarget),
|
||||
FloatExe(FloatTarget),
|
||||
FloatTitle(FloatTarget),
|
||||
/// Show a JSON representation of the current window manager state
|
||||
State,
|
||||
/// Change focus to the window in the specified direction
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
Focus(Focus),
|
||||
/// Move the focused window in the specified direction
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
Move(Move),
|
||||
/// Stack the focused window in the specified direction
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
Stack(Stack),
|
||||
/// Resize the focused window in the specified direction
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
Resize(Resize),
|
||||
/// Unstack the focused window
|
||||
Unstack,
|
||||
/// Cycle the focused stack in the specified cycle direction
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
CycleStack(CycleStack),
|
||||
/// Move the focused window to the specified monitor
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
MoveToMonitor(MoveToMonitor),
|
||||
/// Move the focused window to the specified workspace
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
MoveToWorkspace(MoveToWorkspace),
|
||||
/// Focus the specified monitor
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
FocusMonitor(FocusMonitor),
|
||||
/// Focus the specified workspace on the focused monitor
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
FocusWorkspace(FocusWorkspace),
|
||||
/// Create and append a new workspace on the focused monitor
|
||||
NewWorkspace,
|
||||
/// Adjust container padding on the focused workspace
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
AdjustContainerPadding(PaddingAdjustment),
|
||||
/// Adjust workspace padding on the focused workspace
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
AdjustWorkspacePadding(PaddingAdjustment),
|
||||
/// Flip the layout on the focused workspace (BSP only)
|
||||
FlipLayout(FlipLayout),
|
||||
/// Promote the focused window to the top of the tree
|
||||
Promote,
|
||||
/// Force the retiling of all managed windows
|
||||
Retile,
|
||||
/// Create at least this many workspaces for the specified monitor
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
EnsureWorkspaces(EnsureWorkspaces),
|
||||
/// Set the container padding for the specified workspace
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
ContainerPadding(SizeForMonitorWorkspace),
|
||||
/// Set the workspace padding for the specified workspace
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
WorkspacePadding(SizeForMonitorWorkspace),
|
||||
/// Set the layout for the specified workspace
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
WorkspaceLayout(WorkspaceLayout),
|
||||
/// Enable or disable window tiling for the specified workspace
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
WorkspaceTiling(WorkspaceTiling),
|
||||
/// Set the workspace name for the specified workspace
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
WorkspaceName(WorkspaceName),
|
||||
/// Toggle the window manager on and off across all monitors
|
||||
TogglePause,
|
||||
/// Toggle window tiling on the focused workspace
|
||||
ToggleTiling,
|
||||
/// Toggle floating mode for the focused window
|
||||
ToggleFloat,
|
||||
/// Toggle monocle mode for the focused container
|
||||
ToggleMonocle,
|
||||
/// Restore all hidden windows (debugging command)
|
||||
RestoreWindows,
|
||||
/// Reload ~/komorebi.ahk (if it exists)
|
||||
ReloadConfiguration,
|
||||
/// Toggle the automatic reloading of ~/komorebi.ahk (if it exists)
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
WatchConfiguration(WatchConfiguration),
|
||||
/// Add a rule to always float the specified application
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
FloatRule(ApplicationTarget),
|
||||
/// Identify an application that closes to the system tray
|
||||
#[clap(setting = AppSettings::ArgRequiredElseHelp)]
|
||||
IdentifyTrayApplication(ApplicationTarget),
|
||||
AdjustContainerPadding(SizingAdjustment),
|
||||
AdjustWorkspacePadding(SizingAdjustment),
|
||||
FlipLayout(LayoutFlip),
|
||||
FocusFollowsMouse(BooleanState),
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
struct WorkspaceCountForMonitor {
|
||||
monitor: usize,
|
||||
workspace_count: usize,
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
struct SizeForMonitorWorkspace {
|
||||
monitor: usize,
|
||||
workspace: usize,
|
||||
size: i32,
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
struct NameForMonitorWorkspace {
|
||||
monitor: usize,
|
||||
workspace: usize,
|
||||
value: String,
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
struct LayoutForMonitorWorkspace {
|
||||
monitor: usize,
|
||||
workspace: usize,
|
||||
layout: Layout,
|
||||
}
|
||||
|
||||
fn on_or_off(s: &str) -> Result<bool, &'static str> {
|
||||
match s {
|
||||
"enable" => Ok(true),
|
||||
"disable" => Ok(false),
|
||||
// in order to not break backwards compat for mouse follows focus
|
||||
"on" => Ok(true),
|
||||
"off" => Ok(false),
|
||||
_ => Err("expected `enable` or `disable`"),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
struct TilingForMonitorWorkspace {
|
||||
monitor: usize,
|
||||
workspace: usize,
|
||||
#[clap(parse(try_from_str = on_or_off))]
|
||||
tile: bool,
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
struct Target {
|
||||
number: usize,
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
struct SizingAdjustment {
|
||||
sizing: Sizing,
|
||||
adjustment: i32,
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
struct FloatTarget {
|
||||
id: String,
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
struct ApplicationTarget {
|
||||
identifier: ApplicationIdentifier,
|
||||
id: String,
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
struct Resize {
|
||||
edge: OperationDirection,
|
||||
sizing: Sizing,
|
||||
}
|
||||
|
||||
#[derive(Clap)]
|
||||
enum BooleanState {
|
||||
Enable,
|
||||
Disable,
|
||||
/// Enable or disable focus follows mouse for the operating system
|
||||
FocusFollowsMouse(FocusFollowsMouse),
|
||||
}
|
||||
|
||||
pub fn send_message(bytes: &[u8]) -> Result<()> {
|
||||
@@ -163,8 +259,8 @@ fn main() -> Result<()> {
|
||||
let opts: Opts = Opts::parse();
|
||||
|
||||
match opts.subcmd {
|
||||
SubCommand::Focus(direction) => {
|
||||
send_message(&*SocketMessage::FocusWindow(direction).as_bytes()?)?;
|
||||
SubCommand::Focus(arg) => {
|
||||
send_message(&*SocketMessage::FocusWindow(arg.operation_direction).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::Promote => {
|
||||
send_message(&*SocketMessage::Promote.as_bytes()?)?;
|
||||
@@ -175,47 +271,35 @@ fn main() -> Result<()> {
|
||||
SubCommand::Retile => {
|
||||
send_message(&*SocketMessage::Retile.as_bytes()?)?;
|
||||
}
|
||||
SubCommand::Move(direction) => {
|
||||
send_message(&*SocketMessage::MoveWindow(direction).as_bytes()?)?;
|
||||
SubCommand::Move(arg) => {
|
||||
send_message(&*SocketMessage::MoveWindow(arg.operation_direction).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::MoveToMonitor(display) => {
|
||||
send_message(
|
||||
&*SocketMessage::MoveContainerToMonitorNumber(display.number).as_bytes()?,
|
||||
)?;
|
||||
SubCommand::MoveToMonitor(arg) => {
|
||||
send_message(&*SocketMessage::MoveContainerToMonitorNumber(arg.target).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::MoveToWorkspace(workspace) => {
|
||||
send_message(
|
||||
&*SocketMessage::MoveContainerToWorkspaceNumber(workspace.number).as_bytes()?,
|
||||
)?;
|
||||
SubCommand::MoveToWorkspace(arg) => {
|
||||
send_message(&*SocketMessage::MoveContainerToWorkspaceNumber(arg.target).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::ContainerPadding(gap) => {
|
||||
SubCommand::ContainerPadding(arg) => {
|
||||
send_message(
|
||||
&*SocketMessage::ContainerPadding(gap.monitor, gap.workspace, gap.size)
|
||||
&*SocketMessage::ContainerPadding(arg.monitor, arg.workspace, arg.size)
|
||||
.as_bytes()?,
|
||||
)?;
|
||||
}
|
||||
SubCommand::WorkspacePadding(gap) => {
|
||||
SubCommand::WorkspacePadding(arg) => {
|
||||
send_message(
|
||||
&*SocketMessage::WorkspacePadding(gap.monitor, gap.workspace, gap.size)
|
||||
&*SocketMessage::WorkspacePadding(arg.monitor, arg.workspace, arg.size)
|
||||
.as_bytes()?,
|
||||
)?;
|
||||
}
|
||||
SubCommand::AdjustWorkspacePadding(sizing_adjustment) => {
|
||||
SubCommand::AdjustWorkspacePadding(arg) => {
|
||||
send_message(
|
||||
&*SocketMessage::AdjustWorkspacePadding(
|
||||
sizing_adjustment.sizing,
|
||||
sizing_adjustment.adjustment,
|
||||
)
|
||||
.as_bytes()?,
|
||||
&*SocketMessage::AdjustWorkspacePadding(arg.sizing, arg.adjustment).as_bytes()?,
|
||||
)?;
|
||||
}
|
||||
SubCommand::AdjustContainerPadding(sizing_adjustment) => {
|
||||
SubCommand::AdjustContainerPadding(arg) => {
|
||||
send_message(
|
||||
&*SocketMessage::AdjustContainerPadding(
|
||||
sizing_adjustment.sizing,
|
||||
sizing_adjustment.adjustment,
|
||||
)
|
||||
.as_bytes()?,
|
||||
&*SocketMessage::AdjustContainerPadding(arg.sizing, arg.adjustment).as_bytes()?,
|
||||
)?;
|
||||
}
|
||||
SubCommand::ToggleTiling => {
|
||||
@@ -227,15 +311,15 @@ fn main() -> Result<()> {
|
||||
SubCommand::ToggleMonocle => {
|
||||
send_message(&*SocketMessage::ToggleMonocle.as_bytes()?)?;
|
||||
}
|
||||
SubCommand::WorkspaceLayout(layout) => {
|
||||
SubCommand::WorkspaceLayout(arg) => {
|
||||
send_message(
|
||||
&*SocketMessage::WorkspaceLayout(layout.monitor, layout.workspace, layout.layout)
|
||||
&*SocketMessage::WorkspaceLayout(arg.monitor, arg.workspace, arg.layout)
|
||||
.as_bytes()?,
|
||||
)?;
|
||||
}
|
||||
SubCommand::WorkspaceTiling(layout) => {
|
||||
SubCommand::WorkspaceTiling(arg) => {
|
||||
send_message(
|
||||
&*SocketMessage::WorkspaceTiling(layout.monitor, layout.workspace, layout.tile)
|
||||
&*SocketMessage::WorkspaceTiling(arg.monitor, arg.workspace, arg.tile.into())
|
||||
.as_bytes()?,
|
||||
)?;
|
||||
}
|
||||
@@ -253,32 +337,34 @@ fn main() -> Result<()> {
|
||||
SubCommand::Stop => {
|
||||
send_message(&*SocketMessage::Stop.as_bytes()?)?;
|
||||
}
|
||||
SubCommand::FloatClass(target) => {
|
||||
send_message(&*SocketMessage::FloatClass(target.id).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::FloatExe(target) => {
|
||||
send_message(&*SocketMessage::FloatExe(target.id).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::FloatTitle(target) => {
|
||||
send_message(&*SocketMessage::FloatTitle(target.id).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::Stack(direction) => {
|
||||
send_message(&*SocketMessage::StackWindow(direction).as_bytes()?)?;
|
||||
SubCommand::FloatRule(arg) => match arg.identifier {
|
||||
ApplicationIdentifier::Exe => {
|
||||
send_message(&*SocketMessage::FloatExe(arg.id).as_bytes()?)?;
|
||||
}
|
||||
ApplicationIdentifier::Class => {
|
||||
send_message(&*SocketMessage::FloatClass(arg.id).as_bytes()?)?;
|
||||
}
|
||||
ApplicationIdentifier::Title => {
|
||||
send_message(&*SocketMessage::FloatTitle(arg.id).as_bytes()?)?;
|
||||
}
|
||||
},
|
||||
SubCommand::Stack(arg) => {
|
||||
send_message(&*SocketMessage::StackWindow(arg.operation_direction).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::Unstack => {
|
||||
send_message(&*SocketMessage::UnstackWindow.as_bytes()?)?;
|
||||
}
|
||||
SubCommand::CycleStack(direction) => {
|
||||
send_message(&*SocketMessage::CycleStack(direction).as_bytes()?)?;
|
||||
SubCommand::CycleStack(arg) => {
|
||||
send_message(&*SocketMessage::CycleStack(arg.cycle_direction).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::FlipLayout(flip) => {
|
||||
send_message(&*SocketMessage::FlipLayout(flip).as_bytes()?)?;
|
||||
SubCommand::FlipLayout(arg) => {
|
||||
send_message(&*SocketMessage::FlipLayout(arg.layout_flip).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::FocusMonitor(target) => {
|
||||
send_message(&*SocketMessage::FocusMonitorNumber(target.number).as_bytes()?)?;
|
||||
SubCommand::FocusMonitor(arg) => {
|
||||
send_message(&*SocketMessage::FocusMonitorNumber(arg.target).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::FocusWorkspace(target) => {
|
||||
send_message(&*SocketMessage::FocusWorkspaceNumber(target.number).as_bytes()?)?;
|
||||
SubCommand::FocusWorkspace(arg) => {
|
||||
send_message(&*SocketMessage::FocusWorkspaceNumber(arg.target).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::NewWorkspace => {
|
||||
send_message(&*SocketMessage::NewWorkspace.as_bytes()?)?;
|
||||
@@ -344,8 +430,8 @@ fn main() -> Result<()> {
|
||||
SubCommand::Resize(resize) => {
|
||||
send_message(&*SocketMessage::ResizeWindow(resize.edge, resize.sizing).as_bytes()?)?;
|
||||
}
|
||||
SubCommand::FocusFollowsMouse(enable) => {
|
||||
let enable = match enable {
|
||||
SubCommand::FocusFollowsMouse(arg) => {
|
||||
let enable = match arg.boolean_state {
|
||||
BooleanState::Enable => true,
|
||||
BooleanState::Disable => false,
|
||||
};
|
||||
@@ -355,8 +441,8 @@ fn main() -> Result<()> {
|
||||
SubCommand::ReloadConfiguration => {
|
||||
send_message(&*SocketMessage::ReloadConfiguration.as_bytes()?)?;
|
||||
}
|
||||
SubCommand::WatchConfiguration(enable) => {
|
||||
let enable = match enable {
|
||||
SubCommand::WatchConfiguration(arg) => {
|
||||
let enable = match arg.boolean_state {
|
||||
BooleanState::Enable => true,
|
||||
BooleanState::Disable => false,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user