From cc196db04615676fc8b74910ccc68ac08c45d1a3 Mon Sep 17 00:00:00 2001 From: LGUG2Z Date: Mon, 11 Nov 2024 16:27:43 -0800 Subject: [PATCH] feat(cli): add cycle-stack-index cmd This commit adds a new komorebi command "cycle-stack-index" which allows the user to manipulate the index position of the focused window in the focused stack by swapping it with either the previous or the next window until the desired index position has been found. --- komorebi/src/core/mod.rs | 1 + komorebi/src/process_command.rs | 4 ++++ komorebi/src/window_manager.rs | 33 +++++++++++++++++++++++++++++++++ komorebic/src/main.rs | 7 +++++++ 4 files changed, 45 insertions(+) diff --git a/komorebi/src/core/mod.rs b/komorebi/src/core/mod.rs index 3f2a2399..779bf33f 100644 --- a/komorebi/src/core/mod.rs +++ b/komorebi/src/core/mod.rs @@ -49,6 +49,7 @@ pub enum SocketMessage { StackWindow(OperationDirection), UnstackWindow, CycleStack(CycleDirection), + CycleStackIndex(CycleDirection), FocusStackWindow(usize), StackAll, UnstackAll, diff --git a/komorebi/src/process_command.rs b/komorebi/src/process_command.rs index 117b19f0..a4072064 100644 --- a/komorebi/src/process_command.rs +++ b/komorebi/src/process_command.rs @@ -247,6 +247,10 @@ impl WindowManager { self.cycle_container_window_in_direction(direction)?; self.focused_window()?.focus(self.mouse_follows_focus)?; } + SocketMessage::CycleStackIndex(direction) => { + self.cycle_container_window_index_in_direction(direction)?; + self.focused_window()?.focus(self.mouse_follows_focus)?; + } SocketMessage::FocusStackWindow(idx) => { // In case you are using this command on a bar on a monitor // different from the currently focused one, you'd want that diff --git a/komorebi/src/window_manager.rs b/komorebi/src/window_manager.rs index 9f4916b3..d4cb0463 100644 --- a/komorebi/src/window_manager.rs +++ b/komorebi/src/window_manager.rs @@ -2022,6 +2022,39 @@ impl WindowManager { self.update_focused_workspace(self.mouse_follows_focus, true) } + #[tracing::instrument(skip(self))] + pub fn cycle_container_window_index_in_direction( + &mut self, + direction: CycleDirection, + ) -> Result<()> { + self.handle_unmanaged_window_behaviour()?; + + tracing::info!("cycling container window index"); + + let container = + if let Some(container) = self.focused_workspace_mut()?.monocle_container_mut() { + container + } else { + self.focused_container_mut()? + }; + + let len = NonZeroUsize::new(container.windows().len()) + .ok_or_else(|| anyhow!("there must be at least one window in a container"))?; + + if len.get() == 1 { + bail!("there is only one window in this container"); + } + + let current_idx = container.focused_window_idx(); + let next_idx = direction.next_idx(current_idx, len); + container.windows_mut().swap(current_idx, next_idx); + + container.focus_window(next_idx); + container.load_focused_window(); + + self.update_focused_workspace(self.mouse_follows_focus, true) + } + #[tracing::instrument(skip(self))] pub fn focus_container_window(&mut self, idx: usize) -> Result<()> { self.handle_unmanaged_window_behaviour()?; diff --git a/komorebic/src/main.rs b/komorebic/src/main.rs index 7c60031e..245c2c39 100644 --- a/komorebic/src/main.rs +++ b/komorebic/src/main.rs @@ -160,6 +160,7 @@ gen_enum_subcommand_args! { CycleMoveWorkspaceToMonitor: CycleDirection, Stack: OperationDirection, CycleStack: CycleDirection, + CycleStackIndex: CycleDirection, FlipLayout: Axis, ChangeLayout: DefaultLayout, CycleLayout: CycleDirection, @@ -985,6 +986,9 @@ enum SubCommand { /// Cycle the focused stack in the specified cycle direction #[clap(arg_required_else_help = true)] CycleStack(CycleStack), + /// Cycle the index of the focused window in the focused stack in the specified cycle direction + #[clap(arg_required_else_help = true)] + CycleStackIndex(CycleStackIndex), /// Focus the specified window index in the focused stack #[clap(arg_required_else_help = true)] FocusStackWindow(FocusStackWindow), @@ -2305,6 +2309,9 @@ Stop-Process -Name:komorebi -ErrorAction SilentlyContinue SubCommand::CycleStack(arg) => { send_message(&SocketMessage::CycleStack(arg.cycle_direction))?; } + SubCommand::CycleStackIndex(arg) => { + send_message(&SocketMessage::CycleStackIndex(arg.cycle_direction))?; + } SubCommand::ChangeLayout(arg) => { send_message(&SocketMessage::ChangeLayout(arg.default_layout))?; }