Add ctrl-w _ and ctrl-w = (#21227)

Conrad Irwin created

Closes #ISSUE

Release Notes:

- vim: Add support for `ctrl-w _` and `ctrl-w =`

Change summary

assets/keymaps/vim.json            |  2 ++
crates/vim/src/vim.rs              | 29 ++++++++++++++++++++++++++---
crates/workspace/src/pane_group.rs | 19 ++++++++++++++++++-
crates/workspace/src/workspace.rs  |  9 +++++++++
4 files changed, 55 insertions(+), 4 deletions(-)

Detailed changes

assets/keymaps/vim.json 🔗

@@ -561,6 +561,8 @@
       "ctrl-w <": ["vim::ResizePane", "Narrow"],
       "ctrl-w -": ["vim::ResizePane", "Shorten"],
       "ctrl-w +": ["vim::ResizePane", "Lengthen"],
+      "ctrl-w _": "vim::MaximizePane",
+      "ctrl-w =": "vim::ResetPaneSizes",
       "ctrl-w g t": "pane::ActivateNextItem",
       "ctrl-w ctrl-g t": "pane::ActivateNextItem",
       "ctrl-w g shift-t": "pane::ActivatePrevItem",

crates/vim/src/vim.rs 🔗

@@ -41,7 +41,7 @@ use state::{Mode, Operator, RecordedSelection, SearchState, VimGlobals};
 use std::{mem, ops::Range, sync::Arc};
 use surrounds::SurroundsType;
 use theme::ThemeSettings;
-use ui::{IntoElement, VisualContext};
+use ui::{px, IntoElement, VisualContext};
 use vim_mode_setting::VimModeSetting;
 use workspace::{self, Pane, ResizeIntent, Workspace};
 
@@ -79,7 +79,9 @@ actions!(
         InnerObject,
         FindForward,
         FindBackward,
-        OpenDefaultKeymap
+        OpenDefaultKeymap,
+        MaximizePane,
+        ResetPaneSizes,
     ]
 );
 
@@ -117,8 +119,29 @@ pub fn init(cx: &mut AppContext) {
             });
         });
 
+        workspace.register_action(|workspace, _: &ResetPaneSizes, cx| {
+            workspace.reset_pane_sizes(cx);
+        });
+
+        workspace.register_action(|workspace, _: &MaximizePane, cx| {
+            let pane = workspace.active_pane();
+            let Some(size) = workspace.bounding_box_for_pane(&pane) else {
+                return;
+            };
+
+            let theme = ThemeSettings::get_global(cx);
+            let height = theme.buffer_font_size(cx) * theme.buffer_line_height.value();
+
+            let desired_size = if let Some(count) = Vim::take_count(cx) {
+                height * count
+            } else {
+                px(10000.)
+            };
+            workspace.resize_pane(Axis::Vertical, desired_size - size.size.height, cx)
+        });
+
         workspace.register_action(|workspace, action: &ResizePane, cx| {
-            let count = Vim::take_count(cx.window_context()).unwrap_or(1) as f32;
+            let count = Vim::take_count(cx).unwrap_or(1) as f32;
             let theme = ThemeSettings::get_global(cx);
             let Ok(font_id) = cx.text_system().font_id(&theme.buffer_font) else {
                 return;

crates/workspace/src/pane_group.rs 🔗

@@ -105,6 +105,15 @@ impl PaneGroup {
         };
     }
 
+    pub fn reset_pane_sizes(&mut self) {
+        match &mut self.root {
+            Member::Pane(_) => {}
+            Member::Axis(axis) => {
+                let _ = axis.reset_pane_sizes();
+            }
+        };
+    }
+
     pub fn swap(&mut self, from: &View<Pane>, to: &View<Pane>) {
         match &mut self.root {
             Member::Pane(_) => {}
@@ -460,6 +469,15 @@ impl PaneAxis {
         }
     }
 
+    fn reset_pane_sizes(&self) {
+        *self.flexes.lock() = vec![1.; self.members.len()];
+        for member in self.members.iter() {
+            if let Member::Axis(axis) = member {
+                axis.reset_pane_sizes();
+            }
+        }
+    }
+
     fn resize(
         &mut self,
         pane: &View<Pane>,
@@ -759,7 +777,6 @@ pub enum ResizeIntent {
 }
 
 mod element {
-
     use std::mem;
     use std::{cell::RefCell, iter, rc::Rc, sync::Arc};
 

crates/workspace/src/workspace.rs 🔗

@@ -2946,6 +2946,10 @@ impl Workspace {
         }
     }
 
+    pub fn bounding_box_for_pane(&self, pane: &View<Pane>) -> Option<Bounds<Pixels>> {
+        self.center.bounding_box_for_pane(pane)
+    }
+
     pub fn find_pane_in_direction(
         &mut self,
         direction: SplitDirection,
@@ -2994,6 +2998,11 @@ impl Workspace {
         cx.notify();
     }
 
+    pub fn reset_pane_sizes(&mut self, cx: &mut ViewContext<Self>) {
+        self.center.reset_pane_sizes();
+        cx.notify();
+    }
+
     fn handle_pane_focused(&mut self, pane: View<Pane>, cx: &mut ViewContext<Self>) {
         // This is explicitly hoisted out of the following check for pane identity as
         // terminal panel panes are not registered as a center panes.