diff --git a/assets/keymaps/vim.json b/assets/keymaps/vim.json index c11a474c68..6228f6def6 100644 --- a/assets/keymaps/vim.json +++ b/assets/keymaps/vim.json @@ -197,6 +197,7 @@ "d": ["vim::PushOperator", "Delete"], "shift-d": "vim::DeleteToEndOfLine", "shift-j": "vim::JoinLines", + "g shift-j": "vim::JoinLinesNoWhitespace", "y": ["vim::PushOperator", "Yank"], "shift-y": "vim::YankLine", "i": "vim::InsertBefore", @@ -278,6 +279,7 @@ "g shift-i": "vim::VisualInsertFirstNonWhiteSpace", "g shift-a": "vim::VisualInsertEndOfLine", "shift-j": "vim::JoinLines", + "g shift-j": "vim::JoinLinesNoWhitespace", "r": ["vim::PushOperator", "Replace"], "ctrl-c": ["vim::SwitchMode", "Normal"], "escape": ["vim::SwitchMode", "Normal"], diff --git a/crates/editor/src/actions.rs b/crates/editor/src/actions.rs index a2bc64c4b5..ede5916b06 100644 --- a/crates/editor/src/actions.rs +++ b/crates/editor/src/actions.rs @@ -204,7 +204,7 @@ impl_actions!( ToggleCodeActions, ToggleComments, UnfoldAt, - FoldAtLevel + FoldAtLevel, ] ); diff --git a/crates/editor/src/editor.rs b/crates/editor/src/editor.rs index a217cda0f1..b11832e1b1 100644 --- a/crates/editor/src/editor.rs +++ b/crates/editor/src/editor.rs @@ -5851,7 +5851,7 @@ impl Editor { }); } - pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext) { + pub fn join_lines_impl(&mut self, insert_whitespace: bool, cx: &mut ViewContext) { if self.read_only(cx) { return; } @@ -5893,11 +5893,12 @@ impl Editor { let indent = snapshot.indent_size_for_line(next_line_row); let start_of_next_line = Point::new(next_line_row.0, indent.len); - let replace = if snapshot.line_len(next_line_row) > indent.len { - " " - } else { - "" - }; + let replace = + if snapshot.line_len(next_line_row) > indent.len && insert_whitespace { + " " + } else { + "" + }; this.buffer.update(cx, |buffer, cx| { buffer.edit([(end_of_line..start_of_next_line, replace)], None, cx) @@ -5911,6 +5912,10 @@ impl Editor { }); } + pub fn join_lines(&mut self, _: &JoinLines, cx: &mut ViewContext) { + self.join_lines_impl(true, cx); + } + pub fn sort_lines_case_sensitive( &mut self, _: &SortLinesCaseSensitive, diff --git a/crates/vim/src/normal.rs b/crates/vim/src/normal.rs index bde3c12027..df01f2affc 100644 --- a/crates/vim/src/normal.rs +++ b/crates/vim/src/normal.rs @@ -44,6 +44,8 @@ actions!( InsertLineAbove, InsertLineBelow, InsertAtPrevious, + JoinLines, + JoinLinesNoWhitespace, DeleteLeft, DeleteRight, ChangeToEndOfLine, @@ -53,7 +55,6 @@ actions!( ChangeCase, ConvertToUpperCase, ConvertToLowerCase, - JoinLines, ToggleComments, Undo, Redo, @@ -108,25 +109,11 @@ pub(crate) fn register(editor: &mut Editor, cx: &mut ViewContext) { ); }); Vim::action(editor, cx, |vim, _: &JoinLines, cx| { - vim.record_current_action(cx); - let mut times = Vim::take_count(cx).unwrap_or(1); - if vim.mode.is_visual() { - times = 1; - } else if times > 1 { - // 2J joins two lines together (same as J or 1J) - times -= 1; - } + vim.join_lines_impl(true, cx); + }); - vim.update_editor(cx, |_, editor, cx| { - editor.transact(cx, |editor, cx| { - for _ in 0..times { - editor.join_lines(&Default::default(), cx) - } - }) - }); - if vim.mode.is_visual() { - vim.switch_mode(Mode::Normal, true, cx) - } + Vim::action(editor, cx, |vim, _: &JoinLinesNoWhitespace, cx| { + vim.join_lines_impl(false, cx); }); Vim::action(editor, cx, |vim, _: &Undo, cx| { @@ -401,6 +388,28 @@ impl Vim { }); } + fn join_lines_impl(&mut self, insert_whitespace: bool, cx: &mut ViewContext) { + self.record_current_action(cx); + let mut times = Vim::take_count(cx).unwrap_or(1); + if self.mode.is_visual() { + times = 1; + } else if times > 1 { + // 2J joins two lines together (same as J or 1J) + times -= 1; + } + + self.update_editor(cx, |_, editor, cx| { + editor.transact(cx, |editor, cx| { + for _ in 0..times { + editor.join_lines_impl(insert_whitespace, cx) + } + }) + }); + if self.mode.is_visual() { + self.switch_mode(Mode::Normal, true, cx) + } + } + fn yank_line(&mut self, _: &YankLine, cx: &mut ViewContext) { let count = Vim::take_count(cx); self.yank_motion(motion::Motion::CurrentLine, count, cx) diff --git a/crates/vim/src/test.rs b/crates/vim/src/test.rs index 947353e2d3..25488c9146 100644 --- a/crates/vim/src/test.rs +++ b/crates/vim/src/test.rs @@ -367,6 +367,46 @@ async fn test_join_lines(cx: &mut gpui::TestAppContext) { two three fourˇ five six "}); + + cx.set_shared_state(indoc! {" + ˇone + two + three + four + five + six + "}) + .await; + cx.simulate_shared_keystrokes("g shift-j").await; + cx.shared_state().await.assert_eq(indoc! {" + oneˇtwo + three + four + five + six + "}); + cx.simulate_shared_keystrokes("3 g shift-j").await; + cx.shared_state().await.assert_eq(indoc! {" + onetwothreeˇfour + five + six + "}); + + cx.set_shared_state(indoc! {" + ˇone + two + three + four + five + six + "}) + .await; + cx.simulate_shared_keystrokes("j v 3 j g shift-j").await; + cx.shared_state().await.assert_eq(indoc! {" + one + twothreefourˇfive + six + "}); } #[cfg(target_os = "macos")] diff --git a/crates/vim/test_data/test_join_lines.json b/crates/vim/test_data/test_join_lines.json index b4bc5c30e1..55aa8b1dcb 100644 --- a/crates/vim/test_data/test_join_lines.json +++ b/crates/vim/test_data/test_join_lines.json @@ -11,3 +11,19 @@ {"Key":"j"} {"Key":"shift-j"} {"Get":{"state":"one\ntwo three fourˇ five\nsix\n","mode":"Normal"}} +{"Put":{"state":"ˇone\ntwo\nthree\nfour\nfive\nsix\n"}} +{"Key":"g"} +{"Key":"shift-j"} +{"Get":{"state":"oneˇtwo\nthree\nfour\nfive\nsix\n","mode":"Normal"}} +{"Key":"3"} +{"Key":"g"} +{"Key":"shift-j"} +{"Get":{"state":"onetwothreeˇfour\nfive\nsix\n","mode":"Normal"}} +{"Put":{"state":"ˇone\ntwo\nthree\nfour\nfive\nsix\n"}} +{"Key":"j"} +{"Key":"v"} +{"Key":"3"} +{"Key":"j"} +{"Key":"g"} +{"Key":"shift-j"} +{"Get":{"state":"one\ntwothreefourˇfive\nsix\n","mode":"Normal"}}