Add keybinding to swap pane items (#15583)

tepek2 and Peter Tripp created

- Rearrange tabs (left: `ctrl-shift-pageup`, right: `ctrl-shift-pagedown`) like Chrome

Co-authored-by: Peter Tripp <peter@zed.dev>

Change summary

assets/keymaps/default-linux.json |  2 
assets/keymaps/default-macos.json |  2 
crates/workspace/src/pane.rs      | 24 +++++++++
docs/src/key-bindings.md          | 82 ++++++++++++++++----------------
4 files changed, 70 insertions(+), 40 deletions(-)

Detailed changes

assets/keymaps/default-linux.json 🔗

@@ -245,6 +245,8 @@
     "bindings": {
       "ctrl-pageup": "pane::ActivatePrevItem",
       "ctrl-pagedown": "pane::ActivateNextItem",
+      "ctrl-shift-pageup": "pane::SwapItemLeft",
+      "ctrl-shift-pagedown": "pane::SwapItemRight",
       "ctrl-w": "pane::CloseActiveItem",
       "ctrl-f4": "pane::CloseActiveItem",
       "alt-ctrl-t": "pane::CloseInactiveItems",

assets/keymaps/default-macos.json 🔗

@@ -285,6 +285,8 @@
       "cmd-}": "pane::ActivateNextItem",
       "alt-cmd-left": "pane::ActivatePrevItem",
       "alt-cmd-right": "pane::ActivateNextItem",
+      "ctrl-shift-pageup": "pane::SwapItemLeft",
+      "ctrl-shift-pagedown": "pane::SwapItemRight",
       "cmd-w": "pane::CloseActiveItem",
       "alt-cmd-t": "pane::CloseInactiveItems",
       "ctrl-alt-cmd-w": "workspace::CloseInactiveTabsAndPanes",

crates/workspace/src/pane.rs 🔗

@@ -158,6 +158,8 @@ actions!(
         SplitDown,
         SplitHorizontal,
         SplitVertical,
+        SwapItemLeft,
+        SwapItemRight,
         TogglePreviewTab,
         TogglePinTab,
     ]
@@ -1054,6 +1056,26 @@ impl Pane {
         self.activate_item(index, activate_pane, activate_pane, cx);
     }
 
+    pub fn swap_item_left(&mut self, cx: &mut ViewContext<Self>) {
+        let index = self.active_item_index;
+        if index == 0 {
+            return;
+        }
+
+        self.items.swap(index, index - 1);
+        self.activate_item(index - 1, true, true, cx);
+    }
+
+    pub fn swap_item_right(&mut self, cx: &mut ViewContext<Self>) {
+        let index = self.active_item_index;
+        if index + 1 == self.items.len() {
+            return;
+        }
+
+        self.items.swap(index, index + 1);
+        self.activate_item(index + 1, true, true, cx);
+    }
+
     pub fn close_active_item(
         &mut self,
         action: &CloseActiveItem,
@@ -2574,6 +2596,8 @@ impl Render for Pane {
             .on_action(cx.listener(|pane: &mut Pane, _: &ActivateNextItem, cx| {
                 pane.activate_next_item(true, cx);
             }))
+            .on_action(cx.listener(|pane, _: &SwapItemLeft, cx| pane.swap_item_left(cx)))
+            .on_action(cx.listener(|pane, _: &SwapItemRight, cx| pane.swap_item_right(cx)))
             .on_action(cx.listener(|pane, action, cx| {
                 pane.toggle_pin_tab(action, cx);
             }))

docs/src/key-bindings.md 🔗

@@ -405,46 +405,48 @@ TBD: Add Column with Linux shortcuts
 
 #### Pane
 
-| **Command**                   | **Target**     | **Default Shortcut**    |
-| ----------------------------- | -------------- | ----------------------- |
-| Activate item 1               | Pane           | `Control + 1`           |
-| Activate item 2               | Pane           | `Control + 2`           |
-| Activate item 3               | Pane           | `Control + 3`           |
-| Activate item 4               | Pane           | `Control + 4`           |
-| Activate item 5               | Pane           | `Control + 5`           |
-| Activate item 6               | Pane           | `Control + 6`           |
-| Activate item 7               | Pane           | `Control + 7`           |
-| Activate item 8               | Pane           | `Control + 8`           |
-| Activate item 9               | Pane           | `Control + 9`           |
-| Activate last item            | Pane           | `Control + 0`           |
-| Activate next item            | Pane           | `Alt + ⌘ + Right`       |
-| Activate next item            | Pane           | `⌘ + }`                 |
-| Activate prev item            | Pane           | `Alt + ⌘ + Left`        |
-| Activate prev item            | Pane           | `⌘ + {`                 |
-| Close active item             | Pane           | `⌘ + W`                 |
-| Close all items               | Pane           | `⌘ + K, ⌘ + W`          |
-| Close clean items             | Pane           | `⌘ + K, U`              |
-| Close inactive items          | Pane           | `Alt + ⌘ + T`           |
-| Go back                       | Pane           | `Control + -`           |
-| Go forward                    | Pane           | `Control + Shift + _`   |
-| Reopen closed item            | Pane           | `⌘ + Shift + T`         |
-| Split down                    | Pane           | `⌘ + K, Down`           |
-| Split left                    | Pane           | `⌘ + K, Left`           |
-| Split right                   | Pane           | `⌘ + K, Right`          |
-| Split up                      | Pane           | `⌘ + K, Up`             |
-| Toggle filters                | Project Search | `Alt + ⌘ + F`           |
-| Toggle focus                  | Project Search | `⌘ + F`                 |
-| Toggle focus                  | Project Search | `⌘ + Shift + F`         |
-| Activate regex mode           | Search         | `Alt + ⌘ + G`           |
-| Activate text mode            | Search         | `Alt + ⌘ + X`           |
-| Cycle mode                    | Search         | `Alt + Tab`             |
-| Select all matches            | Search         | `Alt + Enter`           |
-| Select next match             | Search         | `⌘ + G`                 |
-| Select prev match             | Search         | `⌘ + Shift + G`         |
-| Toggle case sensitive         | Search         | `Alt + ⌘ + C`           |
-| Toggle replace                | Search         | `⌘ + Shift + H`         |
-| Toggle whole word             | Search         | `Alt + ⌘ + W`           |
-| Close inactive tabs and panes | Workspace      | `Control + Alt + ⌘ + W` |
+| **Command**                   | **Target**     | **Default Shortcut**          |
+| ----------------------------- | -------------- | ----------------------------- |
+| Activate item 1               | Pane           | `Control + 1`                 |
+| Activate item 2               | Pane           | `Control + 2`                 |
+| Activate item 3               | Pane           | `Control + 3`                 |
+| Activate item 4               | Pane           | `Control + 4`                 |
+| Activate item 5               | Pane           | `Control + 5`                 |
+| Activate item 6               | Pane           | `Control + 6`                 |
+| Activate item 7               | Pane           | `Control + 7`                 |
+| Activate item 8               | Pane           | `Control + 8`                 |
+| Activate item 9               | Pane           | `Control + 9`                 |
+| Activate last item            | Pane           | `Control + 0`                 |
+| Activate next item            | Pane           | `Alt + ⌘ + Right`             |
+| Activate next item            | Pane           | `⌘ + }`                       |
+| Activate prev item            | Pane           | `Alt + ⌘ + Left`              |
+| Activate prev item            | Pane           | `⌘ + {`                       |
+| Swap item to left             | Pane           | `Control + Shift + Page Up`   |
+| Swap item to right            | Pane           | `Control + Shift + Page Down` |
+| Close active item             | Pane           | `⌘ + W`                       |
+| Close all items               | Pane           | `⌘ + K, ⌘ + W`                |
+| Close clean items             | Pane           | `⌘ + K, U`                    |
+| Close inactive items          | Pane           | `Alt + ⌘ + T`                 |
+| Go back                       | Pane           | `Control + -`                 |
+| Go forward                    | Pane           | `Control + Shift + _`         |
+| Reopen closed item            | Pane           | `⌘ + Shift + T`               |
+| Split down                    | Pane           | `⌘ + K, Down`                 |
+| Split left                    | Pane           | `⌘ + K, Left`                 |
+| Split right                   | Pane           | `⌘ + K, Right`                |
+| Split up                      | Pane           | `⌘ + K, Up`                   |
+| Toggle filters                | Project Search | `Alt + ⌘ + F`                 |
+| Toggle focus                  | Project Search | `⌘ + F`                       |
+| Toggle focus                  | Project Search | `⌘ + Shift + F`               |
+| Activate regex mode           | Search         | `Alt + ⌘ + G`                 |
+| Activate text mode            | Search         | `Alt + ⌘ + X`                 |
+| Cycle mode                    | Search         | `Alt + Tab`                   |
+| Select all matches            | Search         | `Alt + Enter`                 |
+| Select next match             | Search         | `⌘ + G`                       |
+| Select prev match             | Search         | `⌘ + Shift + G`               |
+| Toggle case sensitive         | Search         | `Alt + ⌘ + C`                 |
+| Toggle replace                | Search         | `⌘ + Shift + H`               |
+| Toggle whole word             | Search         | `Alt + ⌘ + W`                 |
+| Close inactive tabs and panes | Workspace      | `Control + Alt + ⌘ + W`       |
 
 #### Buffer Search Bar