diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index 34228530d2d398348d57d71ae41654dacb479712..5ff1dc196a82d0c3226253c4b8d892058598b4e3 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -857,6 +857,8 @@ "ctrl-w shift-right": "workspace::SwapPaneRight", "ctrl-w shift-up": "workspace::SwapPaneUp", "ctrl-w shift-down": "workspace::SwapPaneDown", + "ctrl-w x": "workspace::SwapPaneAdjacent", + "ctrl-w ctrl-x": "workspace::SwapPaneAdjacent", "ctrl-w shift-h": "workspace::MovePaneLeft", "ctrl-w shift-l": "workspace::MovePaneRight", "ctrl-w shift-k": "workspace::MovePaneUp", diff --git a/crates/workspace/src/pane_group.rs b/crates/workspace/src/pane_group.rs index 36898b127bdd749a9c1867a97bd72dfd6f4e15ea..c9d98977139ed644cf5f3bfb7eb26d94ca081d19 100644 --- a/crates/workspace/src/pane_group.rs +++ b/crates/workspace/src/pane_group.rs @@ -963,6 +963,15 @@ impl SplitDirection { Self::Down | Self::Right => true, } } + + pub fn opposite(&self) -> SplitDirection { + match self { + Self::Down => Self::Up, + Self::Up => Self::Down, + Self::Left => Self::Right, + Self::Right => Self::Left, + } + } } mod element { diff --git a/crates/workspace/src/workspace.rs b/crates/workspace/src/workspace.rs index 96fed9f65517bd0005ff27907e6f888edd7a48f9..cf102fc16109555971defbdc279e89738582ab74 100644 --- a/crates/workspace/src/workspace.rs +++ b/crates/workspace/src/workspace.rs @@ -437,6 +437,8 @@ actions!( SwapPaneUp, /// Swaps the current pane with the one below. SwapPaneDown, + // Swaps the current pane with the first available adjacent pane (searching in order: below, above, right, left) and activates that pane. + SwapPaneAdjacent, /// Move the current pane to be at the far left. MovePaneLeft, /// Move the current pane to be at the far right. @@ -5823,6 +5825,21 @@ impl Workspace { .on_action(cx.listener(|workspace, _: &SwapPaneDown, _, cx| { workspace.swap_pane_in_direction(SplitDirection::Down, cx) })) + .on_action(cx.listener(|workspace, _: &SwapPaneAdjacent, window, cx| { + const DIRECTION_PRIORITY: [SplitDirection; 4] = [ + SplitDirection::Down, + SplitDirection::Up, + SplitDirection::Right, + SplitDirection::Left, + ]; + for dir in DIRECTION_PRIORITY { + if workspace.find_pane_in_direction(dir, cx).is_some() { + workspace.swap_pane_in_direction(dir, cx); + workspace.activate_pane_in_direction(dir.opposite(), window, cx); + break; + } + } + })) .on_action(cx.listener(|workspace, _: &MovePaneLeft, _, cx| { workspace.move_pane_to_border(SplitDirection::Left, cx) }))