Skip to content

Commit

Permalink
Add support for resizing panes using vim motions (#21038)
Browse files Browse the repository at this point in the history
Closes #8628

Release Notes:

- Added support for resizing the current pane using vim keybinds with
the intention to follow the functionality of vim
  - "ctrl-w +" to make a pane taller 
  - "ctrl-w -" to make the pane shorter
  - "ctrl-w >" to make a pane wider
  - "ctrl-w <" to make the pane narrower
- Changed vim pre_count and post_count to globals to allow for other
crates to use the vim count. In this case, it allows for resizing by
more than one unit. For example, "10 ctrl-w -" will decrease the height
of the pane 10 times more than "ctrl-w -"
- This pr does **not** add keybinds for making all panes in an axis
equal size and does **not** add support for resizing docks. This is
mentioned because these could be implied by the original issue

---------

Co-authored-by: Conrad Irwin <[email protected]>
  • Loading branch information
AidanV and ConradIrwin authored Nov 27, 2024
1 parent d75d345 commit f702575
Show file tree
Hide file tree
Showing 25 changed files with 251 additions and 68 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions assets/keymaps/vim.json
Original file line number Diff line number Diff line change
Expand Up @@ -557,6 +557,10 @@
"ctrl-w shift-l": ["workspace::SwapPaneInDirection", "Right"],
"ctrl-w shift-k": ["workspace::SwapPaneInDirection", "Up"],
"ctrl-w shift-j": ["workspace::SwapPaneInDirection", "Down"],
"ctrl-w >": ["vim::ResizePane", "Widen"],
"ctrl-w <": ["vim::ResizePane", "Narrow"],
"ctrl-w -": ["vim::ResizePane", "Shorten"],
"ctrl-w +": ["vim::ResizePane", "Lengthen"],
"ctrl-w g t": "pane::ActivateNextItem",
"ctrl-w ctrl-g t": "pane::ActivateNextItem",
"ctrl-w g shift-t": "pane::ActivatePrevItem",
Expand Down
1 change: 1 addition & 0 deletions crates/vim/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ serde.workspace = true
serde_derive.workspace = true
serde_json.workspace = true
settings.workspace = true
theme.workspace = true
tokio = { version = "1.15", features = ["full"], optional = true }
ui.workspace = true
util.workspace = true
Expand Down
2 changes: 1 addition & 1 deletion crates/vim/src/change_list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {

impl Vim {
fn move_to_change(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
let count = self.take_count(cx).unwrap_or(1);
let count = Vim::take_count(cx).unwrap_or(1);
if self.change_list.is_empty() {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion crates/vim/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
let Some(workspace) = vim.workspace(cx) else {
return;
};
let count = vim.take_count(cx).unwrap_or(1);
let count = Vim::take_count(cx).unwrap_or(1);
workspace.update(cx, |workspace, cx| {
command_palette::CommandPalette::toggle(
workspace,
Expand Down
4 changes: 2 additions & 2 deletions crates/vim/src/indent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ actions!(vim, [Indent, Outdent,]);
pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
Vim::action(editor, cx, |vim, _: &Indent, cx| {
vim.record_current_action(cx);
let count = vim.take_count(cx).unwrap_or(1);
let count = Vim::take_count(cx).unwrap_or(1);
vim.store_visual_marks(cx);
vim.update_editor(cx, |vim, editor, cx| {
editor.transact(cx, |editor, cx| {
Expand All @@ -34,7 +34,7 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {

Vim::action(editor, cx, |vim, _: &Outdent, cx| {
vim.record_current_action(cx);
let count = vim.take_count(cx).unwrap_or(1);
let count = Vim::take_count(cx).unwrap_or(1);
vim.store_visual_marks(cx);
vim.update_editor(cx, |vim, editor, cx| {
editor.transact(cx, |editor, cx| {
Expand Down
2 changes: 1 addition & 1 deletion crates/vim/src/insert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ impl Vim {
self.sync_vim_settings(cx);
return;
}
let count = self.take_count(cx).unwrap_or(1);
let count = Vim::take_count(cx).unwrap_or(1);
self.stop_recording_immediately(action.boxed_clone(), cx);
if count <= 1 || Vim::globals(cx).dot_replaying {
self.create_mark("^".into(), false, cx);
Expand Down
14 changes: 11 additions & 3 deletions crates/vim/src/mode_indicator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use gpui::{div, Element, Render, Subscription, View, ViewContext, WeakView};
use itertools::Itertools;
use workspace::{item::ItemHandle, ui::prelude::*, StatusItemView};

use crate::{Vim, VimEvent};
use crate::{Vim, VimEvent, VimGlobals};

/// The ModeIndicator displays the current mode in the status bar.
pub struct ModeIndicator {
Expand Down Expand Up @@ -68,14 +68,22 @@ impl ModeIndicator {

let vim = vim.read(cx);
recording
.chain(vim.pre_count.map(|count| format!("{}", count)))
.chain(
cx.global::<VimGlobals>()
.pre_count
.map(|count| format!("{}", count)),
)
.chain(vim.selected_register.map(|reg| format!("\"{reg}")))
.chain(
vim.operator_stack
.iter()
.map(|item| item.status().to_string()),
)
.chain(vim.post_count.map(|count| format!("{}", count)))
.chain(
cx.global::<VimGlobals>()
.post_count
.map(|count| format!("{}", count)),
)
.collect::<Vec<_>>()
.join("")
}
Expand Down
4 changes: 2 additions & 2 deletions crates/vim/src/motion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ impl Vim {
self.pop_operator(cx);
}

let count = self.take_count(cx);
let count = Vim::take_count(cx);
let active_operator = self.active_operator();
let mut waiting_operator: Option<Operator> = None;
match self.mode {
Expand All @@ -510,7 +510,7 @@ impl Vim {
self.clear_operator(cx);
if let Some(operator) = waiting_operator {
self.push_operator(operator, cx);
self.pre_count = count
Vim::globals(cx).pre_count = count
}
}
}
Expand Down
18 changes: 9 additions & 9 deletions crates/vim/src/normal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,17 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {

Vim::action(editor, cx, |vim, _: &DeleteLeft, cx| {
vim.record_current_action(cx);
let times = vim.take_count(cx);
let times = Vim::take_count(cx);
vim.delete_motion(Motion::Left, times, cx);
});
Vim::action(editor, cx, |vim, _: &DeleteRight, cx| {
vim.record_current_action(cx);
let times = vim.take_count(cx);
let times = Vim::take_count(cx);
vim.delete_motion(Motion::Right, times, cx);
});
Vim::action(editor, cx, |vim, _: &ChangeToEndOfLine, cx| {
vim.start_recording(cx);
let times = vim.take_count(cx);
let times = Vim::take_count(cx);
vim.change_motion(
Motion::EndOfLine {
display_lines: false,
Expand All @@ -98,7 +98,7 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
});
Vim::action(editor, cx, |vim, _: &DeleteToEndOfLine, cx| {
vim.record_current_action(cx);
let times = vim.take_count(cx);
let times = Vim::take_count(cx);
vim.delete_motion(
Motion::EndOfLine {
display_lines: false,
Expand All @@ -109,7 +109,7 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
});
Vim::action(editor, cx, |vim, _: &JoinLines, cx| {
vim.record_current_action(cx);
let mut times = vim.take_count(cx).unwrap_or(1);
let mut times = Vim::take_count(cx).unwrap_or(1);
if vim.mode.is_visual() {
times = 1;
} else if times > 1 {
Expand All @@ -130,15 +130,15 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
});

Vim::action(editor, cx, |vim, _: &Undo, cx| {
let times = vim.take_count(cx);
let times = Vim::take_count(cx);
vim.update_editor(cx, |_, editor, cx| {
for _ in 0..times.unwrap_or(1) {
editor.undo(&editor::actions::Undo, cx);
}
});
});
Vim::action(editor, cx, |vim, _: &Redo, cx| {
let times = vim.take_count(cx);
let times = Vim::take_count(cx);
vim.update_editor(cx, |_, editor, cx| {
for _ in 0..times.unwrap_or(1) {
editor.redo(&editor::actions::Redo, cx);
Expand Down Expand Up @@ -396,7 +396,7 @@ impl Vim {
}

fn yank_line(&mut self, _: &YankLine, cx: &mut ViewContext<Self>) {
let count = self.take_count(cx);
let count = Vim::take_count(cx);
self.yank_motion(motion::Motion::CurrentLine, count, cx)
}

Expand All @@ -416,7 +416,7 @@ impl Vim {
}

pub(crate) fn normal_replace(&mut self, text: Arc<str>, cx: &mut ViewContext<Self>) {
let count = self.take_count(cx).unwrap_or(1);
let count = Vim::take_count(cx).unwrap_or(1);
self.stop_recording(cx);
self.update_editor(cx, |_, editor, cx| {
editor.transact(cx, |editor, cx| {
Expand Down
2 changes: 1 addition & 1 deletion crates/vim/src/normal/case.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ impl Vim {
{
self.record_current_action(cx);
self.store_visual_marks(cx);
let count = self.take_count(cx).unwrap_or(1) as u32;
let count = Vim::take_count(cx).unwrap_or(1) as u32;

self.update_editor(cx, |vim, editor, cx| {
let mut ranges = Vec::new();
Expand Down
4 changes: 2 additions & 2 deletions crates/vim/src/normal/increment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ impl_actions!(vim, [Increment, Decrement]);
pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
Vim::action(editor, cx, |vim, action: &Increment, cx| {
vim.record_current_action(cx);
let count = vim.take_count(cx).unwrap_or(1);
let count = Vim::take_count(cx).unwrap_or(1);
let step = if action.step { 1 } else { 0 };
vim.increment(count as i64, step, cx)
});
Vim::action(editor, cx, |vim, action: &Decrement, cx| {
vim.record_current_action(cx);
let count = vim.take_count(cx).unwrap_or(1);
let count = Vim::take_count(cx).unwrap_or(1);
let step = if action.step { -1 } else { 0 };
vim.increment(-(count as i64), step, cx)
});
Expand Down
2 changes: 1 addition & 1 deletion crates/vim/src/normal/paste.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ impl Vim {
pub fn paste(&mut self, action: &Paste, cx: &mut ViewContext<Self>) {
self.record_current_action(cx);
self.store_visual_marks(cx);
let count = self.take_count(cx).unwrap_or(1);
let count = Vim::take_count(cx).unwrap_or(1);

self.update_editor(cx, |vim, editor, cx| {
let text_layout_details = editor.text_layout_details(cx);
Expand Down
4 changes: 2 additions & 2 deletions crates/vim/src/normal/repeat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,7 +158,7 @@ impl Vim {
}

pub(crate) fn replay_register(&mut self, mut register: char, cx: &mut ViewContext<Self>) {
let mut count = self.take_count(cx).unwrap_or(1);
let mut count = Vim::take_count(cx).unwrap_or(1);
self.clear_operator(cx);

let globals = Vim::globals(cx);
Expand All @@ -184,7 +184,7 @@ impl Vim {
}

pub(crate) fn repeat(&mut self, from_insert_mode: bool, cx: &mut ViewContext<Self>) {
let count = self.take_count(cx);
let count = Vim::take_count(cx);
let Some((mut actions, selection, mode)) = Vim::update_globals(cx, |globals, _| {
let actions = globals.recorded_actions.clone();
if actions.is_empty() {
Expand Down
2 changes: 1 addition & 1 deletion crates/vim/src/normal/scroll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ impl Vim {
cx: &mut ViewContext<Self>,
by: fn(c: Option<f32>) -> ScrollAmount,
) {
let amount = by(self.take_count(cx).map(|c| c as f32));
let amount = by(Vim::take_count(cx).map(|c| c as f32));
self.update_editor(cx, |_, editor, cx| {
scroll_editor(editor, move_cursor, &amount, cx)
});
Expand Down
6 changes: 3 additions & 3 deletions crates/vim/src/normal/search.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ impl Vim {
} else {
Direction::Next
};
let count = self.take_count(cx).unwrap_or(1);
let count = Vim::take_count(cx).unwrap_or(1);
let prior_selections = self.editor_selections(cx);
pane.update(cx, |pane, cx| {
if let Some(search_bar) = pane.toolbar().read(cx).item_of_type::<BufferSearchBar>() {
Expand Down Expand Up @@ -226,7 +226,7 @@ impl Vim {

pub fn move_to_match_internal(&mut self, direction: Direction, cx: &mut ViewContext<Self>) {
let Some(pane) = self.pane(cx) else { return };
let count = self.take_count(cx).unwrap_or(1);
let count = Vim::take_count(cx).unwrap_or(1);
let prior_selections = self.editor_selections(cx);

let success = pane.update(cx, |pane, cx| {
Expand Down Expand Up @@ -264,7 +264,7 @@ impl Vim {
cx: &mut ViewContext<Self>,
) {
let Some(pane) = self.pane(cx) else { return };
let count = self.take_count(cx).unwrap_or(1);
let count = Vim::take_count(cx).unwrap_or(1);
let prior_selections = self.editor_selections(cx);
let vim = cx.view().clone();

Expand Down
4 changes: 2 additions & 2 deletions crates/vim/src/normal/substitute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ actions!(vim, [Substitute, SubstituteLine]);
pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
Vim::action(editor, cx, |vim, _: &Substitute, cx| {
vim.start_recording(cx);
let count = vim.take_count(cx);
let count = Vim::take_count(cx);
vim.substitute(count, vim.mode == Mode::VisualLine, cx);
});

Expand All @@ -18,7 +18,7 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
if matches!(vim.mode, Mode::VisualBlock | Mode::Visual) {
vim.switch_mode(Mode::VisualLine, false, cx)
}
let count = vim.take_count(cx);
let count = Vim::take_count(cx);
vim.substitute(count, true, cx)
});
}
Expand Down
2 changes: 1 addition & 1 deletion crates/vim/src/replace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ pub fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
if vim.mode != Mode::Replace {
return;
}
let count = vim.take_count(cx);
let count = Vim::take_count(cx);
vim.undo_replace(count, cx)
});
}
Expand Down
2 changes: 1 addition & 1 deletion crates/vim/src/rewrap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ actions!(vim, [Rewrap]);
pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext<Vim>) {
Vim::action(editor, cx, |vim, _: &Rewrap, cx| {
vim.record_current_action(cx);
vim.take_count(cx);
Vim::take_count(cx);
vim.store_visual_marks(cx);
vim.update_editor(cx, |vim, editor, cx| {
editor.transact(cx, |editor, cx| {
Expand Down
5 changes: 5 additions & 0 deletions crates/vim/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,11 @@ pub struct VimGlobals {
pub dot_recording: bool,
pub dot_replaying: bool,

/// pre_count is the number before an operator is specified (3 in 3d2d)
pub pre_count: Option<usize>,
/// post_count is the number after an operator is specified (2 in 3d2d)
pub post_count: Option<usize>,

pub stop_recording_after_next_action: bool,
pub ignore_current_insertion: bool,
pub recorded_count: Option<usize>,
Expand Down
2 changes: 1 addition & 1 deletion crates/vim/src/surrounds.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ impl Vim {
cx: &mut ViewContext<Self>,
) {
self.stop_recording(cx);
let count = self.take_count(cx);
let count = Vim::take_count(cx);
let mode = self.mode;
self.update_editor(cx, |_, editor, cx| {
let text_layout_details = editor.text_layout_details(cx);
Expand Down
Loading

0 comments on commit f702575

Please sign in to comment.