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:
LGUG2Z
2021-08-16 10:25:01 -07:00
parent 7ede5a2dbc
commit 9c55545600
12 changed files with 342 additions and 254 deletions

22
Cargo.lock generated
View File

@@ -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",
]

View File

@@ -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

View File

@@ -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::*,
);

View File

@@ -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"

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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,

View File

@@ -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

View File

@@ -193,6 +193,7 @@ impl WindowManager {
classes.push(id);
}
}
ApplicationIdentifier::Title => {}
},
}

View File

@@ -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"

View File

@@ -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,
};