diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index aed9b78c44..9246bbcaec 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -12,6 +12,8 @@ "down": "vim::Down", "enter": "vim::NextLineStart", "ctrl-m": "vim::NextLineStart", + "+": "vim::NextLineStart", + "-": "vim::PreviousLineStart", "tab": "vim::Tab", "shift-tab": "vim::Tab", "k": "vim::Up", @@ -192,7 +194,6 @@ "ctrl-w g shift-d": "editor::GoToTypeDefinitionSplit", "ctrl-w space": "editor::OpenExcerptsSplit", "ctrl-w g space": "editor::OpenExcerptsSplit", - "-": "pane::RevealInProjectPanel", "ctrl-6": "pane::AlternateFile" } }, diff --git a/crates/vim/src/motion.rs b/crates/vim/src/motion.rs index ed8640ecbc..0e501c838b 100644 --- a/crates/vim/src/motion.rs +++ b/crates/vim/src/motion.rs @@ -91,6 +91,7 @@ pub enum Motion { last_find: Box, }, NextLineStart, + PreviousLineStart, StartOfLineDownward, EndOfLineDownward, GoToColumn, @@ -235,6 +236,7 @@ actions!( EndOfDocument, Matching, NextLineStart, + PreviousLineStart, StartOfLineDownward, EndOfLineDownward, GoToColumn, @@ -353,6 +355,9 @@ pub fn register(workspace: &mut Workspace, _: &mut ViewContext) { workspace.register_action(|_: &mut Workspace, &NextLineStart, cx: _| { motion(Motion::NextLineStart, cx) }); + workspace.register_action(|_: &mut Workspace, &PreviousLineStart, cx: _| { + motion(Motion::PreviousLineStart, cx) + }); workspace.register_action(|_: &mut Workspace, &StartOfLineDownward, cx: _| { motion(Motion::StartOfLineDownward, cx) }); @@ -468,6 +473,7 @@ impl Motion { | EndOfDocument | CurrentLine | NextLineStart + | PreviousLineStart | StartOfLineDownward | StartOfParagraph | WindowTop @@ -537,6 +543,7 @@ impl Motion { | WindowMiddle | WindowBottom | NextLineStart + | PreviousLineStart | ZedSearchResult { .. } | Jump { .. } => false, } @@ -561,7 +568,8 @@ impl Motion { | PreviousWordEnd { .. } | NextSubwordEnd { .. } | PreviousSubwordEnd { .. } - | NextLineStart => true, + | NextLineStart + | PreviousLineStart => true, Left | Backspace | Right @@ -763,6 +771,7 @@ impl Motion { _ => return None, }, NextLineStart => (next_line_start(map, point, times), SelectionGoal::None), + PreviousLineStart => (previous_line_start(map, point, times), SelectionGoal::None), StartOfLineDownward => (next_line_start(map, point, times - 1), SelectionGoal::None), EndOfLineDownward => (last_non_whitespace(map, point, times), SelectionGoal::None), GoToColumn => (go_to_column(map, point, times), SelectionGoal::None), @@ -1655,6 +1664,11 @@ fn next_line_start(map: &DisplaySnapshot, point: DisplayPoint, times: usize) -> first_non_whitespace(map, false, correct_line) } +fn previous_line_start(map: &DisplaySnapshot, point: DisplayPoint, times: usize) -> DisplayPoint { + let correct_line = start_of_relative_buffer_row(map, point, (times as isize) * -1); + first_non_whitespace(map, false, correct_line) +} + fn go_to_column(map: &DisplaySnapshot, point: DisplayPoint, times: usize) -> DisplayPoint { let correct_line = start_of_relative_buffer_row(map, point, 0); right(map, correct_line, times.saturating_sub(1)) diff --git a/crates/vim/src/test.rs b/crates/vim/src/test.rs index b40a5cd9ac..7bac8c5f52 100644 --- a/crates/vim/src/test.rs +++ b/crates/vim/src/test.rs @@ -1279,3 +1279,22 @@ async fn test_find_multibyte(cx: &mut gpui::TestAppContext) { .await .assert_eq(r#""#); } + +#[gpui::test] +async fn test_plus_minus(cx: &mut gpui::TestAppContext) { + let mut cx = NeovimBackedTestContext::new(cx).await; + + cx.set_shared_state(indoc! { + "one + two + thrˇee + "}) + .await; + + cx.simulate_shared_keystrokes("-").await; + cx.shared_state().await.assert_matches(); + cx.simulate_shared_keystrokes("-").await; + cx.shared_state().await.assert_matches(); + cx.simulate_shared_keystrokes("+").await; + cx.shared_state().await.assert_matches(); +} diff --git a/crates/vim/test_data/test_plus_minus.json b/crates/vim/test_data/test_plus_minus.json new file mode 100644 index 0000000000..277d92ef6a --- /dev/null +++ b/crates/vim/test_data/test_plus_minus.json @@ -0,0 +1,7 @@ +{"Put":{"state":"one\n two\nthrˇee\n"}} +{"Key":"-"} +{"Get":{"state":"one\n ˇtwo\nthree\n","mode":"Normal"}} +{"Key":"-"} +{"Get":{"state":"ˇone\n two\nthree\n","mode":"Normal"}} +{"Key":"+"} +{"Get":{"state":"one\n ˇtwo\nthree\n","mode":"Normal"}}