Enable verifying of visual mode selections in neovim backed tests

K Simmons created

Change summary

crates/vim/src/test_contexts/neovim_backed_test_context.rs |  96 ++-
crates/vim/src/visual.rs                                   | 226 +------
crates/vim/test_data/neovim_backed_test_context_works.json |   2 
crates/vim/test_data/test_a.json                           |   2 
crates/vim/test_data/test_backspace.json                   |   2 
crates/vim/test_data/test_change_around_sentence.json      |   0 
crates/vim/test_data/test_change_around_word.json          |   0 
crates/vim/test_data/test_change_in_sentence.json          |   0 
crates/vim/test_data/test_change_in_word.json              |   0 
crates/vim/test_data/test_delete_around_sentence.json      |   0 
crates/vim/test_data/test_delete_around_word.json          |   0 
crates/vim/test_data/test_delete_in_sentence.json          |   0 
crates/vim/test_data/test_delete_in_word.json              |   0 
crates/vim/test_data/test_e.json                           |   0 
crates/vim/test_data/test_enter_visual_mode.json           |   0 
crates/vim/test_data/test_gg.json                          |   2 
crates/vim/test_data/test_h.json                           |   2 
crates/vim/test_data/test_insert_end_of_line.json          |   2 
crates/vim/test_data/test_insert_line_above.json           |   2 
crates/vim/test_data/test_j.json                           |   2 
crates/vim/test_data/test_jump_to_end.json                 |   2 
crates/vim/test_data/test_jump_to_line_boundaries.json     |   1 
crates/vim/test_data/test_k.json                           |   2 
crates/vim/test_data/test_l.json                           |   2 
crates/vim/test_data/test_neovim.json                      |   2 
crates/vim/test_data/test_repeated_cb.json                 |   0 
crates/vim/test_data/test_repeated_ce.json                 |   0 
crates/vim/test_data/test_repeated_cj.json                 |   0 
crates/vim/test_data/test_repeated_cl.json                 |   0 
crates/vim/test_data/test_repeated_word.json               |   0 
crates/vim/test_data/test_visual_delete.json               |   1 
crates/vim/test_data/test_visual_line_delete.json          |   1 
crates/vim/test_data/test_w.json                           |   0 
33 files changed, 129 insertions(+), 220 deletions(-)

Detailed changes

crates/vim/src/test_contexts/neovim_backed_test_context.rs 🔗

@@ -1,5 +1,5 @@
 use std::{
-    ops::{Deref, DerefMut},
+    ops::{Deref, DerefMut, Range},
     path::PathBuf,
 };
 
@@ -145,10 +145,17 @@ impl<'a> NeovimBackedTestContext<'a> {
             self.assertion_context.context()
         );
 
-        let zed_head = self.update_editor(|editor, cx| editor.selections.newest_display(cx).head());
+        let zed_selection = self.update_editor(|editor, cx| editor.selections.newest_display(cx));
+        let mut zed_selection_range = zed_selection.range();
+        // Zed selections adjust themselves to make the end point visually make sense
+        if zed_selection.reversed {
+            *zed_selection_range.end.column_mut() =
+                zed_selection_range.end.column().saturating_sub(1);
+        }
+        let neovim_selection = self.neovim.selection().await;
         assert_eq!(
-            self.neovim.head().await,
-            zed_head,
+            neovim_selection,
+            zed_selection_range,
             "{}",
             self.assertion_context.context()
         );
@@ -234,7 +241,7 @@ impl<'a> DerefMut for NeovimBackedTestContext<'a> {
 #[derive(Serialize, Deserialize)]
 pub enum NeovimData {
     Text(String),
-    Head { row: u32, column: u32 },
+    Selection { start: (u32, u32), end: (u32, u32) },
     Mode(Option<Mode>),
 }
 
@@ -267,6 +274,7 @@ impl NeovimConnection {
                 .await
                 .expect("Could not attach to ui");
 
+            // Makes system act a little more like zed in terms of indentation
             nvim.set_option("smartindent", nvim_rs::Value::Boolean(true))
                 .await
                 .expect("Could not set smartindent on startup");
@@ -319,36 +327,64 @@ impl NeovimConnection {
     }
 
     #[cfg(feature = "neovim")]
-    pub async fn head(&mut self) -> DisplayPoint {
-        let nvim_row: u32 = self
-            .nvim
-            .command_output("echo line('.')")
-            .await
-            .unwrap()
-            .parse::<u32>()
-            .unwrap()
-            - 1; // Neovim rows start at 1
-        let nvim_column: u32 = self
-            .nvim
-            .command_output("echo col('.')")
-            .await
-            .unwrap()
-            .parse::<u32>()
-            .unwrap()
-            - 1; // Neovim columns start at 1
+    pub async fn selection(&mut self) -> Range<DisplayPoint> {
+        let (start, end) = if let Some(Mode::Visual { .. }) = self.mode().await {
+            self.nvim
+                .input("<escape>")
+                .await
+                .expect("Could not exit visual mode");
+            let nvim_buffer = self
+                .nvim
+                .get_current_buf()
+                .await
+                .expect("Could not get neovim buffer");
+            let (start_row, start_col) = nvim_buffer
+                .get_mark("<")
+                .await
+                .expect("Could not get selection start");
+            let (end_row, end_col) = nvim_buffer
+                .get_mark(">")
+                .await
+                .expect("Could not get selection end");
+            self.nvim
+                .input("gv")
+                .await
+                .expect("Could not reselect visual selection");
+
+            (
+                (start_row as u32 - 1, start_col as u32),
+                (end_row as u32 - 1, end_col as u32),
+            )
+        } else {
+            let nvim_row: u32 = self
+                .nvim
+                .command_output("echo line('.')")
+                .await
+                .unwrap()
+                .parse::<u32>()
+                .unwrap()
+                - 1; // Neovim rows start at 1
+            let nvim_column: u32 = self
+                .nvim
+                .command_output("echo col('.')")
+                .await
+                .unwrap()
+                .parse::<u32>()
+                .unwrap()
+                - 1; // Neovim columns start at 1
+
+            ((nvim_row, nvim_column), (nvim_row, nvim_column))
+        };
 
-        self.data.push_back(NeovimData::Head {
-            row: nvim_row,
-            column: nvim_column,
-        });
+        self.data.push_back(NeovimData::Selection { start, end });
 
-        DisplayPoint::new(nvim_row, nvim_column)
+        DisplayPoint::new(start.0, start.1)..DisplayPoint::new(end.0, end.1)
     }
 
     #[cfg(not(feature = "neovim"))]
-    pub async fn head(&mut self) -> DisplayPoint {
-        if let Some(NeovimData::Head { row, column }) = self.data.pop_front() {
-            DisplayPoint::new(row, column)
+    pub async fn selection(&mut self) -> Range<DisplayPoint> {
+        if let Some(NeovimData::Selection { start, end }) = self.data.pop_front() {
+            DisplayPoint::new(start.0, start.1)..DisplayPoint::new(end.0, end.1)
         } else {
             panic!("Invalid test data. Is test deterministic? Try running with '--features neovim' to regenerate");
         }

crates/vim/src/visual.rs 🔗

@@ -280,220 +280,92 @@ pub fn paste(_: &mut Workspace, _: &VisualPaste, cx: &mut ViewContext<Workspace>
 mod test {
     use indoc::indoc;
 
-    use crate::{state::Mode, test_contexts::VimTestContext};
+    use crate::{
+        state::Mode,
+        test_contexts::{NeovimBackedTestContext, VimTestContext},
+    };
 
     #[gpui::test]
     async fn test_enter_visual_mode(cx: &mut gpui::TestAppContext) {
-        let cx = VimTestContext::new(cx, true).await;
-        let mut cx = cx
-            .binding(["v", "w", "j"])
-            .mode_after(Mode::Visual { line: false });
-        cx.assert(
-            indoc! {"
+        let mut cx = NeovimBackedTestContext::new(cx)
+            .await
+            .binding(["v", "w", "j"]);
+        cx.assert_all(indoc! {"
                 The ˇquick brown
-                fox jumps over
-                the lazy dog"},
-            indoc! {"
-                The «quick brown
-                fox jumps ˇ»over
-                the lazy dog"},
-        );
-        cx.assert(
-            indoc! {"
-                The quick brown
-                fox jumps over
-                the ˇlazy dog"},
-            indoc! {"
-                The quick brown
-                fox jumps over
-                the «lazy ˇ»dog"},
-        );
-        cx.assert(
-            indoc! {"
-                The quick brown
                 fox jumps ˇover
-                the lazy dog"},
-            indoc! {"
-                The quick brown
-                fox jumps «over
-                ˇ»the lazy dog"},
-        );
-        let mut cx = cx
-            .binding(["v", "b", "k"])
-            .mode_after(Mode::Visual { line: false });
-        cx.assert(
-            indoc! {"
+                the ˇlazy dog"})
+            .await;
+        let mut cx = cx.binding(["v", "b", "k"]);
+        cx.assert_all(indoc! {"
                 The ˇquick brown
-                fox jumps over
-                the lazy dog"},
-            indoc! {"
-                «ˇThe q»uick brown
-                fox jumps over
-                the lazy dog"},
-        );
-        cx.assert(
-            indoc! {"
-                The quick brown
-                fox jumps over
-                the ˇlazy dog"},
-            indoc! {"
-                The quick brown
-                «ˇfox jumps over
-                the l»azy dog"},
-        );
-        cx.assert(
-            indoc! {"
-                The quick brown
                 fox jumps ˇover
-                the lazy dog"},
-            indoc! {"
-                The «ˇquick brown
-                fox jumps o»ver
-                the lazy dog"},
-        );
+                the ˇlazy dog"})
+            .await;
     }
 
     #[gpui::test]
     async fn test_visual_delete(cx: &mut gpui::TestAppContext) {
-        let cx = VimTestContext::new(cx, true).await;
-        let mut cx = cx.binding(["v", "w", "x"]);
-        cx.assert("The quick ˇbrown", "The quickˇ ");
+        let mut cx = NeovimBackedTestContext::new(cx)
+            .await
+            .binding(["v", "w", "x"]);
+        cx.assert("The quick ˇbrown").await;
         let mut cx = cx.binding(["v", "w", "j", "x"]);
-        cx.assert(
-            indoc! {"
+        cx.assert(indoc! {"
                 The ˇquick brown
                 fox jumps over
-                the lazy dog"},
-            indoc! {"
-                The ˇver
-                the lazy dog"},
-        );
+                the lazy dog"})
+            .await;
         // Test pasting code copied on delete
-        cx.simulate_keystrokes(["j", "p"]);
-        cx.assert_editor_state(indoc! {"
-            The ver
-            the lˇquick brown
-            fox jumps oazy dog"});
+        cx.simulate_shared_keystrokes(["j", "p"]).await;
+        cx.assert_state_matches().await;
 
-        cx.assert(
-            indoc! {"
-                The quick brown
-                fox jumps over
-                the ˇlazy dog"},
-            indoc! {"
-                The quick brown
+        cx.assert_all(indoc! {"
+                The ˇquick brown
                 fox jumps over
-                the ˇog"},
-        );
-        cx.assert(
-            indoc! {"
-                The quick brown
-                fox jumps ˇover
-                the lazy dog"},
-            indoc! {"
-                The quick brown
-                fox jumps ˇhe lazy dog"},
-        );
+                the ˇlazy dog"})
+            .await;
         let mut cx = cx.binding(["v", "b", "k", "x"]);
-        cx.assert(
-            indoc! {"
+        cx.assert_all(indoc! {"
                 The ˇquick brown
-                fox jumps over
-                the lazy dog"},
-            indoc! {"
-                ˇuick brown
-                fox jumps over
-                the lazy dog"},
-        );
-        cx.assert(
-            indoc! {"
-                The quick brown
-                fox jumps over
-                the ˇlazy dog"},
-            indoc! {"
-                The quick brown
-                ˇazy dog"},
-        );
-        cx.assert(
-            indoc! {"
-                The quick brown
                 fox jumps ˇover
-                the lazy dog"},
-            indoc! {"
-                The ˇver
-                the lazy dog"},
-        );
+                the ˇlazy dog"})
+            .await;
     }
 
     #[gpui::test]
     async fn test_visual_line_delete(cx: &mut gpui::TestAppContext) {
-        let cx = VimTestContext::new(cx, true).await;
-        let mut cx = cx.binding(["shift-v", "x"]);
-        cx.assert(
-            indoc! {"
+        let mut cx = NeovimBackedTestContext::new(cx)
+            .await
+            .binding(["shift-v", "x"]);
+        cx.assert(indoc! {"
                 The quˇick brown
                 fox jumps over
-                the lazy dog"},
-            indoc! {"
-                fox juˇmps over
-                the lazy dog"},
-        );
+                the lazy dog"})
+            .await;
         // Test pasting code copied on delete
-        cx.simulate_keystroke("p");
-        cx.assert_editor_state(indoc! {"
-            fox jumps over
-            ˇThe quick brown
-            the lazy dog"});
+        cx.simulate_shared_keystroke("p").await;
+        cx.assert_state_matches().await;
 
-        cx.assert(
-            indoc! {"
+        cx.assert_all(indoc! {"
                 The quick brown
                 fox juˇmps over
-                the lazy dog"},
-            indoc! {"
-                The quick brown
-                the laˇzy dog"},
-        );
-        cx.assert(
-            indoc! {"
-                The quick brown
-                fox jumps over
-                the laˇzy dog"},
-            indoc! {"
-                The quick brown
-                fox juˇmps over"},
-        );
+                the laˇzy dog"})
+            .await;
         let mut cx = cx.binding(["shift-v", "j", "x"]);
-        cx.assert(
-            indoc! {"
+        cx.assert(indoc! {"
                 The quˇick brown
                 fox jumps over
-                the lazy dog"},
-            "the laˇzy dog",
-        );
+                the lazy dog"})
+            .await;
         // Test pasting code copied on delete
-        cx.simulate_keystroke("p");
-        cx.assert_editor_state(indoc! {"
-            the lazy dog
-            ˇThe quick brown
-            fox jumps over"});
+        cx.simulate_shared_keystroke("p").await;
+        cx.assert_state_matches().await;
 
-        cx.assert(
-            indoc! {"
+        cx.assert_all(indoc! {"
                 The quick brown
                 fox juˇmps over
-                the lazy dog"},
-            "The quˇick brown",
-        );
-        cx.assert(
-            indoc! {"
-                The quick brown
-                fox jumps over
-                the laˇzy dog"},
-            indoc! {"
-                The quick brown
-                fox juˇmps over"},
-        );
+                the laˇzy dog"})
+            .await;
     }
 
     #[gpui::test]

crates/vim/test_data/neovim_backed_test_context_works.json 🔗

@@ -1 +1 @@
-[{"Text":""},{"Head":{"row":0,"column":0}},{"Mode":"Normal"},{"Text":"This is a test"},{"Head":{"row":0,"column":13}},{"Mode":"Normal"}]
+[{"Text":""},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"},{"Text":"This is a test"},{"Mode":"Normal"},{"Selection":{"start":[0,13],"end":[0,13]}},{"Mode":"Normal"}]

crates/vim/test_data/test_a.json 🔗

@@ -1 +1 @@
-[{"Text":"The quick"},{"Head":{"row":0,"column":6}},{"Mode":"Insert"},{"Text":"The quick"},{"Head":{"row":0,"column":9}},{"Mode":"Insert"}]
+[{"Text":"The quick"},{"Mode":"Insert"},{"Selection":{"start":[0,6],"end":[0,6]}},{"Mode":"Insert"},{"Text":"The quick"},{"Mode":"Insert"},{"Selection":{"start":[0,9],"end":[0,9]}},{"Mode":"Insert"}]

crates/vim/test_data/test_backspace.json 🔗

@@ -1 +1 @@
-[{"Text":"The quick\nbrown"},{"Head":{"row":0,"column":0}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Head":{"row":0,"column":4}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Head":{"row":0,"column":8}},{"Mode":"Normal"}]
+[{"Text":"The quick\nbrown"},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Mode":"Normal"},{"Selection":{"start":[0,4],"end":[0,4]}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Mode":"Normal"},{"Selection":{"start":[0,8],"end":[0,8]}},{"Mode":"Normal"}]

crates/vim/test_data/test_gg.json 🔗

@@ -1 +1 @@
-[{"Text":"The quick\n\nbrown fox jumps\nover the lazy dog"},{"Head":{"row":0,"column":5}},{"Mode":"Normal"},{"Text":"The quick\n\nbrown fox jumps\nover the lazy dog"},{"Head":{"row":0,"column":5}},{"Mode":"Normal"},{"Text":"The quick\n\nbrown fox jumps\nover the lazy dog"},{"Head":{"row":0,"column":8}},{"Mode":"Normal"},{"Text":"\n\nbrown fox jumps\nover the lazy dog"},{"Head":{"row":0,"column":0}},{"Mode":"Normal"}]
+[{"Text":"The quick\n\nbrown fox jumps\nover the lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[0,5],"end":[0,5]}},{"Mode":"Normal"},{"Text":"The quick\n\nbrown fox jumps\nover the lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[0,5],"end":[0,5]}},{"Mode":"Normal"},{"Text":"The quick\n\nbrown fox jumps\nover the lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[0,8],"end":[0,8]}},{"Mode":"Normal"},{"Text":"\n\nbrown fox jumps\nover the lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"}]

crates/vim/test_data/test_h.json 🔗

@@ -1 +1 @@
-[{"Text":"The quick\nbrown"},{"Head":{"row":0,"column":0}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Head":{"row":0,"column":4}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Head":{"row":1,"column":0}},{"Mode":"Normal"}]
+[{"Text":"The quick\nbrown"},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Mode":"Normal"},{"Selection":{"start":[0,4],"end":[0,4]}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Mode":"Normal"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Normal"}]

crates/vim/test_data/test_insert_end_of_line.json 🔗

@@ -1 +1 @@
-[{"Text":"\nThe quick\nbrown fox "},{"Head":{"row":0,"column":0}},{"Mode":"Insert"},{"Text":"\nThe quick\nbrown fox "},{"Head":{"row":1,"column":9}},{"Mode":"Insert"},{"Text":"\nThe quick\nbrown fox "},{"Head":{"row":2,"column":10}},{"Mode":"Insert"}]
+[{"Text":"\nThe quick\nbrown fox "},{"Mode":"Insert"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Insert"},{"Text":"\nThe quick\nbrown fox "},{"Mode":"Insert"},{"Selection":{"start":[1,9],"end":[1,9]}},{"Mode":"Insert"},{"Text":"\nThe quick\nbrown fox "},{"Mode":"Insert"},{"Selection":{"start":[2,10],"end":[2,10]}},{"Mode":"Insert"}]

crates/vim/test_data/test_insert_line_above.json 🔗

@@ -1 +1 @@
-[{"Text":"\n"},{"Head":{"row":0,"column":0}},{"Mode":"Insert"},{"Text":"\nThe quick"},{"Head":{"row":0,"column":0}},{"Mode":"Insert"},{"Text":"\nThe quick\nbrown fox\njumps over"},{"Head":{"row":0,"column":0}},{"Mode":"Insert"},{"Text":"The quick\n\nbrown fox\njumps over"},{"Head":{"row":1,"column":0}},{"Mode":"Insert"},{"Text":"The quick\nbrown fox\n\njumps over"},{"Head":{"row":2,"column":0}},{"Mode":"Insert"},{"Text":"The quick\n\n\nbrown fox"},{"Head":{"row":1,"column":0}},{"Mode":"Insert"}]
+[{"Text":"\n"},{"Mode":"Insert"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Insert"},{"Text":"\nThe quick"},{"Mode":"Insert"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Insert"},{"Text":"\nThe quick\nbrown fox\njumps over"},{"Mode":"Insert"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Insert"},{"Text":"The quick\n\nbrown fox\njumps over"},{"Mode":"Insert"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Insert"},{"Text":"The quick\nbrown fox\n\njumps over"},{"Mode":"Insert"},{"Selection":{"start":[2,0],"end":[2,0]}},{"Mode":"Insert"},{"Text":"The quick\n\n\nbrown fox"},{"Mode":"Insert"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Insert"}]

crates/vim/test_data/test_j.json 🔗

@@ -1 +1 @@
-[{"Text":"The quick brown\nfox jumps"},{"Head":{"row":1,"column":0}},{"Mode":"Normal"},{"Text":"The quick brown\nfox jumps"},{"Head":{"row":1,"column":5}},{"Mode":"Normal"},{"Text":"The quick brown\nfox jumps"},{"Head":{"row":1,"column":8}},{"Mode":"Normal"},{"Text":"The quick brown\nfox jumps"},{"Head":{"row":1,"column":0}},{"Mode":"Normal"}]
+[{"Text":"The quick brown\nfox jumps"},{"Mode":"Normal"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Normal"},{"Text":"The quick brown\nfox jumps"},{"Mode":"Normal"},{"Selection":{"start":[1,5],"end":[1,5]}},{"Mode":"Normal"},{"Text":"The quick brown\nfox jumps"},{"Mode":"Normal"},{"Selection":{"start":[1,8],"end":[1,8]}},{"Mode":"Normal"},{"Text":"The quick brown\nfox jumps"},{"Mode":"Normal"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Normal"}]

crates/vim/test_data/test_jump_to_end.json 🔗

@@ -1 +1 @@
-[{"Text":"The quick\n\nbrown fox jumps\nover the lazy dog"},{"Head":{"row":3,"column":4}},{"Mode":"Normal"},{"Text":"The quick\n\nbrown fox jumps\nover the lazy dog"},{"Head":{"row":3,"column":4}},{"Mode":"Normal"},{"Text":"The quick\n\nbrown fox jumps\nover the lazy dog"},{"Head":{"row":3,"column":16}},{"Mode":"Normal"},{"Text":"The quick\n\nbrown"},{"Head":{"row":2,"column":4}},{"Mode":"Normal"},{"Text":"The quick\n\n"},{"Head":{"row":2,"column":0}},{"Mode":"Normal"}]
+[{"Text":"The quick\n\nbrown fox jumps\nover the lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[3,4],"end":[3,4]}},{"Mode":"Normal"},{"Text":"The quick\n\nbrown fox jumps\nover the lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[3,4],"end":[3,4]}},{"Mode":"Normal"},{"Text":"The quick\n\nbrown fox jumps\nover the lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[3,16],"end":[3,16]}},{"Mode":"Normal"},{"Text":"The quick\n\nbrown"},{"Mode":"Normal"},{"Selection":{"start":[2,4],"end":[2,4]}},{"Mode":"Normal"},{"Text":"The quick\n\n"},{"Mode":"Normal"},{"Selection":{"start":[2,0],"end":[2,0]}},{"Mode":"Normal"}]

crates/vim/test_data/test_jump_to_line_boundaries.json 🔗

@@ -1 +1 @@
-[{"Text":"The quick\nbrown"},{"Head":{"row":0,"column":8}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Head":{"row":0,"column":8}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Head":{"row":0,"column":8}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Head":{"row":1,"column":4}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Head":{"row":1,"column":4}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Head":{"row":0,"column":0}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Head":{"row":0,"column":0}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Head":{"row":0,"column":0}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Head":{"row":1,"column":0}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Head":{"row":1,"column":0}},{"Mode":"Normal"}]

crates/vim/test_data/test_k.json 🔗

@@ -1 +1 @@
-[{"Text":"The quick\nbrown fox jumps"},{"Head":{"row":0,"column":0}},{"Mode":"Normal"},{"Text":"The quick\nbrown fox jumps"},{"Head":{"row":0,"column":5}},{"Mode":"Normal"},{"Text":"The quick\nbrown fox jumps"},{"Head":{"row":0,"column":0}},{"Mode":"Normal"},{"Text":"The quick\nbrown fox jumps"},{"Head":{"row":0,"column":7}},{"Mode":"Normal"},{"Text":"The quick\nbrown fox jumps"},{"Head":{"row":0,"column":8}},{"Mode":"Normal"}]
+[{"Text":"The quick\nbrown fox jumps"},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"},{"Text":"The quick\nbrown fox jumps"},{"Mode":"Normal"},{"Selection":{"start":[0,5],"end":[0,5]}},{"Mode":"Normal"},{"Text":"The quick\nbrown fox jumps"},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"},{"Text":"The quick\nbrown fox jumps"},{"Mode":"Normal"},{"Selection":{"start":[0,7],"end":[0,7]}},{"Mode":"Normal"},{"Text":"The quick\nbrown fox jumps"},{"Mode":"Normal"},{"Selection":{"start":[0,8],"end":[0,8]}},{"Mode":"Normal"}]

crates/vim/test_data/test_l.json 🔗

@@ -1 +1 @@
-[{"Text":"The quick\nbrown"},{"Head":{"row":0,"column":1}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Head":{"row":0,"column":6}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Head":{"row":0,"column":8}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Head":{"row":1,"column":1}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Head":{"row":1,"column":4}},{"Mode":"Normal"}]
+[{"Text":"The quick\nbrown"},{"Mode":"Normal"},{"Selection":{"start":[0,1],"end":[0,1]}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Mode":"Normal"},{"Selection":{"start":[0,6],"end":[0,6]}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Mode":"Normal"},{"Selection":{"start":[0,8],"end":[0,8]}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Mode":"Normal"},{"Selection":{"start":[1,1],"end":[1,1]}},{"Mode":"Normal"},{"Text":"The quick\nbrown"},{"Mode":"Normal"},{"Selection":{"start":[1,4],"end":[1,4]}},{"Mode":"Normal"}]

crates/vim/test_data/test_neovim.json 🔗

@@ -1 +1 @@
-[{"Text":"test"},{"Head":{"row":0,"column":0}},{"Mode":"Normal"}]
+[{"Text":"test"},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"}]

crates/vim/test_data/test_visual_delete.json 🔗

@@ -0,0 +1 @@
+[{"Text":"The quick "},{"Mode":"Normal"},{"Selection":{"start":[0,9],"end":[0,9]}},{"Mode":"Normal"},{"Text":"The ver\nthe lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[0,4],"end":[0,4]}},{"Mode":"Normal"},{"Text":"The ver\nthe lquick brown\nfox jumps oazy dog"},{"Mode":"Normal"},{"Selection":{"start":[1,5],"end":[1,5]}},{"Mode":"Normal"},{"Text":"The ver\nthe lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[0,4],"end":[0,4]}},{"Mode":"Normal"},{"Text":"The quick brown\nfox jumps over\nthe og"},{"Mode":"Normal"},{"Selection":{"start":[2,4],"end":[2,4]}},{"Mode":"Normal"},{"Text":"uick brown\nfox jumps over\nthe lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[0,0],"end":[0,0]}},{"Mode":"Normal"},{"Text":"The ver\nthe lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[0,4],"end":[0,4]}},{"Mode":"Normal"},{"Text":"The quick brown\nazy dog"},{"Mode":"Normal"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Normal"}]

crates/vim/test_data/test_visual_line_delete.json 🔗

@@ -0,0 +1 @@
+[{"Text":"fox jumps over\nthe lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[0,6],"end":[0,6]}},{"Mode":"Normal"},{"Text":"fox jumps over\nThe quick brown\nthe lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Normal"},{"Text":"The quick brown\nthe lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[1,6],"end":[1,6]}},{"Mode":"Normal"},{"Text":"The quick brown\nfox jumps over"},{"Mode":"Normal"},{"Selection":{"start":[1,6],"end":[1,6]}},{"Mode":"Normal"},{"Text":"the lazy dog"},{"Mode":"Normal"},{"Selection":{"start":[0,6],"end":[0,6]}},{"Mode":"Normal"},{"Text":"the lazy dog\nThe quick brown\nfox jumps over"},{"Mode":"Normal"},{"Selection":{"start":[1,0],"end":[1,0]}},{"Mode":"Normal"},{"Text":"The quick brown"},{"Mode":"Normal"},{"Selection":{"start":[0,6],"end":[0,6]}},{"Mode":"Normal"},{"Text":"The quick brown\nfox jumps over"},{"Mode":"Normal"},{"Selection":{"start":[1,6],"end":[1,6]}},{"Mode":"Normal"}]