add vim-specific J (with repeatability)

Conrad Irwin created

Change summary

assets/keymaps/vim.json                   |  1 
crates/vim/src/normal.rs                  | 11 ++++-
crates/vim/src/test.rs                    | 49 +++++++++++++++++++++++++
crates/vim/test_data/test_join_lines.json | 13 ++++++
4 files changed, 72 insertions(+), 2 deletions(-)

Detailed changes

assets/keymaps/vim.json 🔗

@@ -451,6 +451,7 @@
       "~": "vim::ChangeCase",
       "shift-i": "vim::InsertBefore",
       "shift-a": "vim::InsertAfter",
+      "shift-j": "vim::JoinLines",
       "r": [
         "vim::PushOperator",
         "Replace"

crates/vim/src/normal.rs 🔗

@@ -110,11 +110,18 @@ pub fn init(cx: &mut AppContext) {
     cx.add_action(|_: &mut Workspace, _: &JoinLines, cx| {
         Vim::update(cx, |vim, cx| {
             vim.record_current_action(cx);
-            let times = vim.pop_number_operator(cx).unwrap_or(1);
+            let mut times = vim.pop_number_operator(cx).unwrap_or(1);
+            if vim.state().mode.is_visual() {
+                times = 1;
+            } else if times > 1 {
+                // 2J joins two lines together (same as J or 1J)
+                times -= 1;
+            }
+
             vim.update_active_editor(cx, |editor, cx| {
                 editor.transact(cx, |editor, cx| {
                     for _ in 0..times {
-                        editor.join_lines(editor::JoinLines, cx)
+                        editor.join_lines(&Default::default(), cx)
                     }
                 })
             })

crates/vim/src/test.rs 🔗

@@ -286,6 +286,55 @@ async fn test_word_characters(cx: &mut gpui::TestAppContext) {
     )
 }
 
+#[gpui::test]
+async fn test_join_lines(cx: &mut gpui::TestAppContext) {
+    let mut cx = NeovimBackedTestContext::new(cx).await;
+
+    cx.set_shared_state(indoc! {"
+      ˇone
+      two
+      three
+      four
+      five
+      six
+      "})
+        .await;
+    cx.simulate_shared_keystrokes(["shift-j"]).await;
+    cx.assert_shared_state(indoc! {"
+          oneˇ two
+          three
+          four
+          five
+          six
+          "})
+        .await;
+    cx.simulate_shared_keystrokes(["3", "shift-j"]).await;
+    cx.assert_shared_state(indoc! {"
+          one two threeˇ four
+          five
+          six
+          "})
+        .await;
+
+    cx.set_shared_state(indoc! {"
+      ˇone
+      two
+      three
+      four
+      five
+      six
+      "})
+        .await;
+    cx.simulate_shared_keystrokes(["j", "v", "3", "j", "shift-j"])
+        .await;
+    cx.assert_shared_state(indoc! {"
+      one
+      two three fourˇ five
+      six
+      "})
+        .await;
+}
+
 #[gpui::test]
 async fn test_wrapped_lines(cx: &mut gpui::TestAppContext) {
     let mut cx = NeovimBackedTestContext::new(cx).await;

crates/vim/test_data/test_join_lines.json 🔗

@@ -0,0 +1,13 @@
+{"Put":{"state":"ˇone\ntwo\nthree\nfour\nfive\nsix\n"}}
+{"Key":"shift-j"}
+{"Get":{"state":"oneˇ two\nthree\nfour\nfive\nsix\n","mode":"Normal"}}
+{"Key":"3"}
+{"Key":"shift-j"}
+{"Get":{"state":"one two threeˇ four\nfive\nsix\n","mode":"Normal"}}
+{"Put":{"state":"ˇone\ntwo\nthree\nfour\nfive\nsix\n"}}
+{"Key":"j"}
+{"Key":"v"}
+{"Key":"3"}
+{"Key":"j"}
+{"Key":"shift-j"}
+{"Get":{"state":"one\ntwo three fourˇ five\nsix\n","mode":"Normal"}}