vim2 (#3597)

Conrad Irwin created

- MOAR TESTS

[[PR Description]]

Release Notes:

- N/A

Change summary

crates/gpui2/src/key_dispatch.rs                   |    6 
crates/gpui2/src/window.rs                         |    7 
crates/vim2/src/insert.rs                          |  184 +-
crates/vim2/src/motion.rs                          |  297 ++--
crates/vim2/src/normal/case.rs                     |   68 
crates/vim2/src/normal/change.rs                   |  740 +++++-----
crates/vim2/src/normal/delete.rs                   |  664 ++++----
crates/vim2/src/normal/increment.rs                |  182 +-
crates/vim2/src/normal/paste.rs                    |  554 +++---
crates/vim2/src/normal/repeat.rs                   |  623 ++++----
crates/vim2/src/normal/scroll.rs                   |  256 +-
crates/vim2/src/normal/search.rs                   |   44 
crates/vim2/src/normal/substitute.rs               |  340 ++--
crates/vim2/src/object.rs                          |  872 ++++++------
crates/vim2/src/test/neovim_backed_test_context.rs |   45 
crates/vim2/src/test/vim_test_context.rs           |   18 
crates/vim2/src/vim.rs                             |    2 
crates/vim2/src/visual.rs                          | 1133 ++++++++-------
18 files changed, 3,023 insertions(+), 3,012 deletions(-)

Detailed changes

crates/gpui2/src/key_dispatch.rs 🔗

@@ -230,6 +230,12 @@ impl DispatchTree {
         }
     }
 
+    pub fn has_pending_keystrokes(&self) -> bool {
+        self.keystroke_matchers
+            .iter()
+            .any(|(_, matcher)| matcher.has_pending_keystrokes())
+    }
+
     pub fn dispatch_path(&self, target: DispatchNodeId) -> SmallVec<[DispatchNodeId; 32]> {
         let mut dispatch_path: SmallVec<[DispatchNodeId; 32]> = SmallVec::new();
         let mut current_node_id = Some(target);

crates/gpui2/src/window.rs 🔗

@@ -1468,6 +1468,13 @@ impl<'a> WindowContext<'a> {
         self.dispatch_keystroke_observers(event, None);
     }
 
+    pub fn has_pending_keystrokes(&self) -> bool {
+        self.window
+            .rendered_frame
+            .dispatch_tree
+            .has_pending_keystrokes()
+    }
+
     fn dispatch_action_on_node(&mut self, node_id: DispatchNodeId, action: Box<dyn Action>) {
         let dispatch_path = self
             .window

crates/vim2/src/insert.rs 🔗

@@ -36,100 +36,90 @@ fn normal_before(_: &mut Workspace, action: &NormalBefore, cx: &mut ViewContext<
     }
 }
 
-// #[cfg(test)]
-// mod test {
-//     use std::sync::Arc;
-
-//     use gpui::executor::Deterministic;
-
-//     use crate::{
-//         state::Mode,
-//         test::{NeovimBackedTestContext, VimTestContext},
-//     };
-
-//     #[gpui::test]
-//     async fn test_enter_and_exit_insert_mode(cx: &mut gpui::TestAppContext) {
-//         let mut cx = VimTestContext::new(cx, true).await;
-//         cx.simulate_keystroke("i");
-//         assert_eq!(cx.mode(), Mode::Insert);
-//         cx.simulate_keystrokes(["T", "e", "s", "t"]);
-//         cx.assert_editor_state("Testˇ");
-//         cx.simulate_keystroke("escape");
-//         assert_eq!(cx.mode(), Mode::Normal);
-//         cx.assert_editor_state("Tesˇt");
-//     }
-
-//     #[gpui::test]
-//     async fn test_insert_with_counts(
-//         deterministic: Arc<Deterministic>,
-//         cx: &mut gpui::TestAppContext,
-//     ) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.set_shared_state("ˇhello\n").await;
-//         cx.simulate_shared_keystrokes(["5", "i", "-", "escape"])
-//             .await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state("----ˇ-hello\n").await;
-
-//         cx.set_shared_state("ˇhello\n").await;
-//         cx.simulate_shared_keystrokes(["5", "a", "-", "escape"])
-//             .await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state("h----ˇ-ello\n").await;
-
-//         cx.simulate_shared_keystrokes(["4", "shift-i", "-", "escape"])
-//             .await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state("---ˇ-h-----ello\n").await;
-
-//         cx.simulate_shared_keystrokes(["3", "shift-a", "-", "escape"])
-//             .await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state("----h-----ello--ˇ-\n").await;
-
-//         cx.set_shared_state("ˇhello\n").await;
-//         cx.simulate_shared_keystrokes(["3", "o", "o", "i", "escape"])
-//             .await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state("hello\noi\noi\noˇi\n").await;
-
-//         cx.set_shared_state("ˇhello\n").await;
-//         cx.simulate_shared_keystrokes(["3", "shift-o", "o", "i", "escape"])
-//             .await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state("oi\noi\noˇi\nhello\n").await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_insert_with_repeat(
-//         deterministic: Arc<Deterministic>,
-//         cx: &mut gpui::TestAppContext,
-//     ) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.set_shared_state("ˇhello\n").await;
-//         cx.simulate_shared_keystrokes(["3", "i", "-", "escape"])
-//             .await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state("--ˇ-hello\n").await;
-//         cx.simulate_shared_keystrokes(["."]).await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state("----ˇ--hello\n").await;
-//         cx.simulate_shared_keystrokes(["2", "."]).await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state("-----ˇ---hello\n").await;
-
-//         cx.set_shared_state("ˇhello\n").await;
-//         cx.simulate_shared_keystrokes(["2", "o", "k", "k", "escape"])
-//             .await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state("hello\nkk\nkˇk\n").await;
-//         cx.simulate_shared_keystrokes(["."]).await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state("hello\nkk\nkk\nkk\nkˇk\n").await;
-//         cx.simulate_shared_keystrokes(["1", "."]).await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state("hello\nkk\nkk\nkk\nkk\nkˇk\n").await;
-//     }
-// }
+#[cfg(test)]
+mod test {
+    use crate::{
+        state::Mode,
+        test::{NeovimBackedTestContext, VimTestContext},
+    };
+
+    #[gpui::test]
+    async fn test_enter_and_exit_insert_mode(cx: &mut gpui::TestAppContext) {
+        let mut cx = VimTestContext::new(cx, true).await;
+        cx.simulate_keystroke("i");
+        assert_eq!(cx.mode(), Mode::Insert);
+        cx.simulate_keystrokes(["T", "e", "s", "t"]);
+        cx.assert_editor_state("Testˇ");
+        cx.simulate_keystroke("escape");
+        assert_eq!(cx.mode(), Mode::Normal);
+        cx.assert_editor_state("Tesˇt");
+    }
+
+    #[gpui::test]
+    async fn test_insert_with_counts(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.set_shared_state("ˇhello\n").await;
+        cx.simulate_shared_keystrokes(["5", "i", "-", "escape"])
+            .await;
+        cx.run_until_parked();
+        cx.assert_shared_state("----ˇ-hello\n").await;
+
+        cx.set_shared_state("ˇhello\n").await;
+        cx.simulate_shared_keystrokes(["5", "a", "-", "escape"])
+            .await;
+        cx.run_until_parked();
+        cx.assert_shared_state("h----ˇ-ello\n").await;
+
+        cx.simulate_shared_keystrokes(["4", "shift-i", "-", "escape"])
+            .await;
+        cx.run_until_parked();
+        cx.assert_shared_state("---ˇ-h-----ello\n").await;
+
+        cx.simulate_shared_keystrokes(["3", "shift-a", "-", "escape"])
+            .await;
+        cx.run_until_parked();
+        cx.assert_shared_state("----h-----ello--ˇ-\n").await;
+
+        cx.set_shared_state("ˇhello\n").await;
+        cx.simulate_shared_keystrokes(["3", "o", "o", "i", "escape"])
+            .await;
+        cx.run_until_parked();
+        cx.assert_shared_state("hello\noi\noi\noˇi\n").await;
+
+        cx.set_shared_state("ˇhello\n").await;
+        cx.simulate_shared_keystrokes(["3", "shift-o", "o", "i", "escape"])
+            .await;
+        cx.run_until_parked();
+        cx.assert_shared_state("oi\noi\noˇi\nhello\n").await;
+    }
+
+    #[gpui::test]
+    async fn test_insert_with_repeat(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.set_shared_state("ˇhello\n").await;
+        cx.simulate_shared_keystrokes(["3", "i", "-", "escape"])
+            .await;
+        cx.run_until_parked();
+        cx.assert_shared_state("--ˇ-hello\n").await;
+        cx.simulate_shared_keystrokes(["."]).await;
+        cx.run_until_parked();
+        cx.assert_shared_state("----ˇ--hello\n").await;
+        cx.simulate_shared_keystrokes(["2", "."]).await;
+        cx.run_until_parked();
+        cx.assert_shared_state("-----ˇ---hello\n").await;
+
+        cx.set_shared_state("ˇhello\n").await;
+        cx.simulate_shared_keystrokes(["2", "o", "k", "k", "escape"])
+            .await;
+        cx.run_until_parked();
+        cx.assert_shared_state("hello\nkk\nkˇk\n").await;
+        cx.simulate_shared_keystrokes(["."]).await;
+        cx.run_until_parked();
+        cx.assert_shared_state("hello\nkk\nkk\nkk\nkˇk\n").await;
+        cx.simulate_shared_keystrokes(["1", "."]).await;
+        cx.run_until_parked();
+        cx.assert_shared_state("hello\nkk\nkk\nkk\nkk\nkˇk\n").await;
+    }
+}

crates/vim2/src/motion.rs 🔗

@@ -952,147 +952,156 @@ pub(crate) fn next_line_end(
     end_of_line(map, false, point)
 }
 
-// #[cfg(test)]
-// mod test {
-
-//     use crate::test::NeovimBackedTestContext;
-//     use indoc::indoc;
-
-//     #[gpui::test]
-//     async fn test_start_end_of_paragraph(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         let initial_state = indoc! {r"ˇabc
-//             def
-
-//             paragraph
-//             the second
-
-//             third and
-//             final"};
-
-//         // goes down once
-//         cx.set_shared_state(initial_state).await;
-//         cx.simulate_shared_keystrokes(["}"]).await;
-//         cx.assert_shared_state(indoc! {r"abc
-//             def
-//             ˇ
-//             paragraph
-//             the second
-
-//             third and
-//             final"})
-//             .await;
-
-//         // goes up once
-//         cx.simulate_shared_keystrokes(["{"]).await;
-//         cx.assert_shared_state(initial_state).await;
-
-//         // goes down twice
-//         cx.simulate_shared_keystrokes(["2", "}"]).await;
-//         cx.assert_shared_state(indoc! {r"abc
-//             def
-
-//             paragraph
-//             the second
-//             ˇ
-
-//             third and
-//             final"})
-//             .await;
-
-//         // goes down over multiple blanks
-//         cx.simulate_shared_keystrokes(["}"]).await;
-//         cx.assert_shared_state(indoc! {r"abc
-//                 def
-
-//                 paragraph
-//                 the second
-
-//                 third and
-//                 finaˇl"})
-//             .await;
-
-//         // goes up twice
-//         cx.simulate_shared_keystrokes(["2", "{"]).await;
-//         cx.assert_shared_state(indoc! {r"abc
-//                 def
-//                 ˇ
-//                 paragraph
-//                 the second
-
-//                 third and
-//                 final"})
-//             .await
-//     }
-
-//     #[gpui::test]
-//     async fn test_matching(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.set_shared_state(indoc! {r"func ˇ(a string) {
-//                 do(something(with<Types>.and_arrays[0, 2]))
-//             }"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["%"]).await;
-//         cx.assert_shared_state(indoc! {r"func (a stringˇ) {
-//                 do(something(with<Types>.and_arrays[0, 2]))
-//             }"})
-//             .await;
-
-//         // test it works on the last character of the line
-//         cx.set_shared_state(indoc! {r"func (a string) ˇ{
-//             do(something(with<Types>.and_arrays[0, 2]))
-//             }"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["%"]).await;
-//         cx.assert_shared_state(indoc! {r"func (a string) {
-//             do(something(with<Types>.and_arrays[0, 2]))
-//             ˇ}"})
-//             .await;
-
-//         // test it works on immediate nesting
-//         cx.set_shared_state("ˇ{()}").await;
-//         cx.simulate_shared_keystrokes(["%"]).await;
-//         cx.assert_shared_state("{()ˇ}").await;
-//         cx.simulate_shared_keystrokes(["%"]).await;
-//         cx.assert_shared_state("ˇ{()}").await;
-
-//         // test it works on immediate nesting inside braces
-//         cx.set_shared_state("{\n    ˇ{()}\n}").await;
-//         cx.simulate_shared_keystrokes(["%"]).await;
-//         cx.assert_shared_state("{\n    {()ˇ}\n}").await;
-
-//         // test it jumps to the next paren on a line
-//         cx.set_shared_state("func ˇboop() {\n}").await;
-//         cx.simulate_shared_keystrokes(["%"]).await;
-//         cx.assert_shared_state("func boop(ˇ) {\n}").await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_comma_semicolon(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.set_shared_state("ˇone two three four").await;
-//         cx.simulate_shared_keystrokes(["f", "o"]).await;
-//         cx.assert_shared_state("one twˇo three four").await;
-//         cx.simulate_shared_keystrokes([","]).await;
-//         cx.assert_shared_state("ˇone two three four").await;
-//         cx.simulate_shared_keystrokes(["2", ";"]).await;
-//         cx.assert_shared_state("one two three fˇour").await;
-//         cx.simulate_shared_keystrokes(["shift-t", "e"]).await;
-//         cx.assert_shared_state("one two threeˇ four").await;
-//         cx.simulate_shared_keystrokes(["3", ";"]).await;
-//         cx.assert_shared_state("oneˇ two three four").await;
-//         cx.simulate_shared_keystrokes([","]).await;
-//         cx.assert_shared_state("one two thˇree four").await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_next_line_start(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-//         cx.set_shared_state("ˇone\n  two\nthree").await;
-//         cx.simulate_shared_keystrokes(["enter"]).await;
-//         cx.assert_shared_state("one\n  ˇtwo\nthree").await;
-//     }
-// }
+#[cfg(test)]
+mod test {
+
+    use crate::test::NeovimBackedTestContext;
+    use indoc::indoc;
+
+    #[gpui::test]
+    async fn test_start_end_of_paragraph(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        let initial_state = indoc! {r"ˇabc
+            def
+
+            paragraph
+            the second
+
+
+
+            third and
+            final"};
+
+        // goes down once
+        cx.set_shared_state(initial_state).await;
+        cx.simulate_shared_keystrokes(["}"]).await;
+        cx.assert_shared_state(indoc! {r"abc
+            def
+            ˇ
+            paragraph
+            the second
+
+
+
+            third and
+            final"})
+            .await;
+
+        // goes up once
+        cx.simulate_shared_keystrokes(["{"]).await;
+        cx.assert_shared_state(initial_state).await;
+
+        // goes down twice
+        cx.simulate_shared_keystrokes(["2", "}"]).await;
+        cx.assert_shared_state(indoc! {r"abc
+            def
+
+            paragraph
+            the second
+            ˇ
+
+
+            third and
+            final"})
+            .await;
+
+        // goes down over multiple blanks
+        cx.simulate_shared_keystrokes(["}"]).await;
+        cx.assert_shared_state(indoc! {r"abc
+                def
+
+                paragraph
+                the second
+
+
+
+                third and
+                finaˇl"})
+            .await;
+
+        // goes up twice
+        cx.simulate_shared_keystrokes(["2", "{"]).await;
+        cx.assert_shared_state(indoc! {r"abc
+                def
+                ˇ
+                paragraph
+                the second
+
+
+
+                third and
+                final"})
+            .await
+    }
+
+    #[gpui::test]
+    async fn test_matching(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.set_shared_state(indoc! {r"func ˇ(a string) {
+                do(something(with<Types>.and_arrays[0, 2]))
+            }"})
+            .await;
+        cx.simulate_shared_keystrokes(["%"]).await;
+        cx.assert_shared_state(indoc! {r"func (a stringˇ) {
+                do(something(with<Types>.and_arrays[0, 2]))
+            }"})
+            .await;
+
+        // test it works on the last character of the line
+        cx.set_shared_state(indoc! {r"func (a string) ˇ{
+            do(something(with<Types>.and_arrays[0, 2]))
+            }"})
+            .await;
+        cx.simulate_shared_keystrokes(["%"]).await;
+        cx.assert_shared_state(indoc! {r"func (a string) {
+            do(something(with<Types>.and_arrays[0, 2]))
+            ˇ}"})
+            .await;
+
+        // test it works on immediate nesting
+        cx.set_shared_state("ˇ{()}").await;
+        cx.simulate_shared_keystrokes(["%"]).await;
+        cx.assert_shared_state("{()ˇ}").await;
+        cx.simulate_shared_keystrokes(["%"]).await;
+        cx.assert_shared_state("ˇ{()}").await;
+
+        // test it works on immediate nesting inside braces
+        cx.set_shared_state("{\n    ˇ{()}\n}").await;
+        cx.simulate_shared_keystrokes(["%"]).await;
+        cx.assert_shared_state("{\n    {()ˇ}\n}").await;
+
+        // test it jumps to the next paren on a line
+        cx.set_shared_state("func ˇboop() {\n}").await;
+        cx.simulate_shared_keystrokes(["%"]).await;
+        cx.assert_shared_state("func boop(ˇ) {\n}").await;
+    }
+
+    #[gpui::test]
+    async fn test_comma_semicolon(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.set_shared_state("ˇone two three four").await;
+        cx.simulate_shared_keystrokes(["f", "o"]).await;
+        cx.assert_shared_state("one twˇo three four").await;
+        cx.simulate_shared_keystrokes([","]).await;
+        cx.assert_shared_state("ˇone two three four").await;
+        cx.simulate_shared_keystrokes(["2", ";"]).await;
+        cx.assert_shared_state("one two three fˇour").await;
+        cx.simulate_shared_keystrokes(["shift-t", "e"]).await;
+        cx.assert_shared_state("one two threeˇ four").await;
+        cx.simulate_shared_keystrokes(["3", ";"]).await;
+        cx.assert_shared_state("oneˇ two three four").await;
+        cx.simulate_shared_keystrokes([","]).await;
+        cx.assert_shared_state("one two thˇree four").await;
+    }
+
+    #[gpui::test]
+    async fn test_next_line_start(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+        cx.set_shared_state("ˇone\n  two\nthree").await;
+        cx.simulate_shared_keystrokes(["enter"]).await;
+        cx.assert_shared_state("one\n  ˇtwo\nthree").await;
+    }
+}

crates/vim2/src/normal/case.rs 🔗

@@ -74,43 +74,43 @@ pub fn change_case(_: &mut Workspace, _: &ChangeCase, cx: &mut ViewContext<Works
         vim.switch_mode(Mode::Normal, true, cx)
     })
 }
-// #[cfg(test)]
-// mod test {
-//     use crate::{state::Mode, test::NeovimBackedTestContext};
+#[cfg(test)]
+mod test {
+    use crate::{state::Mode, test::NeovimBackedTestContext};
 
-//     #[gpui::test]
-//     async fn test_change_case(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-//         cx.set_shared_state("ˇabC\n").await;
-//         cx.simulate_shared_keystrokes(["~"]).await;
-//         cx.assert_shared_state("AˇbC\n").await;
-//         cx.simulate_shared_keystrokes(["2", "~"]).await;
-//         cx.assert_shared_state("ABˇc\n").await;
+    #[gpui::test]
+    async fn test_change_case(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+        cx.set_shared_state("ˇabC\n").await;
+        cx.simulate_shared_keystrokes(["~"]).await;
+        cx.assert_shared_state("AˇbC\n").await;
+        cx.simulate_shared_keystrokes(["2", "~"]).await;
+        cx.assert_shared_state("ABˇc\n").await;
 
-//         // works in visual mode
-//         cx.set_shared_state("a😀C«dÉ1*fˇ»\n").await;
-//         cx.simulate_shared_keystrokes(["~"]).await;
-//         cx.assert_shared_state("a😀CˇDé1*F\n").await;
+        // works in visual mode
+        cx.set_shared_state("a😀C«dÉ1*fˇ»\n").await;
+        cx.simulate_shared_keystrokes(["~"]).await;
+        cx.assert_shared_state("a😀CˇDé1*F\n").await;
 
-//         // works with multibyte characters
-//         cx.simulate_shared_keystrokes(["~"]).await;
-//         cx.set_shared_state("aˇC😀é1*F\n").await;
-//         cx.simulate_shared_keystrokes(["4", "~"]).await;
-//         cx.assert_shared_state("ac😀É1ˇ*F\n").await;
+        // works with multibyte characters
+        cx.simulate_shared_keystrokes(["~"]).await;
+        cx.set_shared_state("aˇC😀é1*F\n").await;
+        cx.simulate_shared_keystrokes(["4", "~"]).await;
+        cx.assert_shared_state("ac😀É1ˇ*F\n").await;
 
-//         // works with line selections
-//         cx.set_shared_state("abˇC\n").await;
-//         cx.simulate_shared_keystrokes(["shift-v", "~"]).await;
-//         cx.assert_shared_state("ˇABc\n").await;
+        // works with line selections
+        cx.set_shared_state("abˇC\n").await;
+        cx.simulate_shared_keystrokes(["shift-v", "~"]).await;
+        cx.assert_shared_state("ˇABc\n").await;
 
-//         // works in visual block mode
-//         cx.set_shared_state("ˇaa\nbb\ncc").await;
-//         cx.simulate_shared_keystrokes(["ctrl-v", "j", "~"]).await;
-//         cx.assert_shared_state("ˇAa\nBb\ncc").await;
+        // works in visual block mode
+        cx.set_shared_state("ˇaa\nbb\ncc").await;
+        cx.simulate_shared_keystrokes(["ctrl-v", "j", "~"]).await;
+        cx.assert_shared_state("ˇAa\nBb\ncc").await;
 
-//         // works with multiple cursors (zed only)
-//         cx.set_state("aˇßcdˇe\n", Mode::Normal);
-//         cx.simulate_keystroke("~");
-//         cx.assert_state("aSSˇcdˇE\n", Mode::Normal);
-//     }
-// }
+        // works with multiple cursors (zed only)
+        cx.set_state("aˇßcdˇe\n", Mode::Normal);
+        cx.simulate_keystroke("~");
+        cx.assert_state("aSSˇcdˇE\n", Mode::Normal);
+    }
+}

crates/vim2/src/normal/change.rs 🔗

@@ -130,373 +130,373 @@ fn expand_changed_word_selection(
     }
 }
 
-// #[cfg(test)]
-// mod test {
-//     use indoc::indoc;
-
-//     use crate::test::NeovimBackedTestContext;
-
-//     #[gpui::test]
-//     async fn test_change_h(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "h"]);
-//         cx.assert("Teˇst").await;
-//         cx.assert("Tˇest").await;
-//         cx.assert("ˇTest").await;
-//         cx.assert(indoc! {"
-//             Test
-//             ˇtest"})
-//             .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_change_backspace(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx)
-//             .await
-//             .binding(["c", "backspace"]);
-//         cx.assert("Teˇst").await;
-//         cx.assert("Tˇest").await;
-//         cx.assert("ˇTest").await;
-//         cx.assert(indoc! {"
-//             Test
-//             ˇtest"})
-//             .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_change_l(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "l"]);
-//         cx.assert("Teˇst").await;
-//         cx.assert("Tesˇt").await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_change_w(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "w"]);
-//         cx.assert("Teˇst").await;
-//         cx.assert("Tˇest test").await;
-//         cx.assert("Testˇ  test").await;
-//         cx.assert(indoc! {"
-//                 Test teˇst
-//                 test"})
-//             .await;
-//         cx.assert(indoc! {"
-//                 Test tesˇt
-//                 test"})
-//             .await;
-//         cx.assert(indoc! {"
-//                 Test test
-//                 ˇ
-//                 test"})
-//             .await;
-
-//         let mut cx = cx.binding(["c", "shift-w"]);
-//         cx.assert("Test teˇst-test test").await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_change_e(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "e"]);
-//         cx.assert("Teˇst Test").await;
-//         cx.assert("Tˇest test").await;
-//         cx.assert(indoc! {"
-//                 Test teˇst
-//                 test"})
-//             .await;
-//         cx.assert(indoc! {"
-//                 Test tesˇt
-//                 test"})
-//             .await;
-//         cx.assert(indoc! {"
-//                 Test test
-//                 ˇ
-//                 test"})
-//             .await;
-
-//         let mut cx = cx.binding(["c", "shift-e"]);
-//         cx.assert("Test teˇst-test test").await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_change_b(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "b"]);
-//         cx.assert("Teˇst Test").await;
-//         cx.assert("Test ˇtest").await;
-//         cx.assert("Test1 test2 ˇtest3").await;
-//         cx.assert(indoc! {"
-//                 Test test
-//                 ˇtest"})
-//             .await;
-//         cx.assert(indoc! {"
-//                 Test test
-//                 ˇ
-//                 test"})
-//             .await;
-
-//         let mut cx = cx.binding(["c", "shift-b"]);
-//         cx.assert("Test test-test ˇtest").await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_change_end_of_line(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "$"]);
-//         cx.assert(indoc! {"
-//             The qˇuick
-//             brown fox"})
-//             .await;
-//         cx.assert(indoc! {"
-//             The quick
-//             ˇ
-//             brown fox"})
-//             .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_change_0(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The qˇuick
-//             brown fox"},
-//             ["c", "0"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The quick
-//             ˇ
-//             brown fox"},
-//             ["c", "0"],
-//         )
-//         .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_change_k(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The quick
-//             brown ˇfox
-//             jumps over"},
-//             ["c", "k"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The quick
-//             brown fox
-//             jumps ˇover"},
-//             ["c", "k"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The qˇuick
-//             brown fox
-//             jumps over"},
-//             ["c", "k"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             ˇ
-//             brown fox
-//             jumps over"},
-//             ["c", "k"],
-//         )
-//         .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_change_j(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The quick
-//             brown ˇfox
-//             jumps over"},
-//             ["c", "j"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The quick
-//             brown fox
-//             jumps ˇover"},
-//             ["c", "j"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The qˇuick
-//             brown fox
-//             jumps over"},
-//             ["c", "j"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The quick
-//             brown fox
-//             ˇ"},
-//             ["c", "j"],
-//         )
-//         .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_change_end_of_document(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The quick
-//             brownˇ fox
-//             jumps over
-//             the lazy"},
-//             ["c", "shift-g"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The quick
-//             brownˇ fox
-//             jumps over
-//             the lazy"},
-//             ["c", "shift-g"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The quick
-//             brown fox
-//             jumps over
-//             the lˇazy"},
-//             ["c", "shift-g"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The quick
-//             brown fox
-//             jumps over
-//             ˇ"},
-//             ["c", "shift-g"],
-//         )
-//         .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_change_gg(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The quick
-//             brownˇ fox
-//             jumps over
-//             the lazy"},
-//             ["c", "g", "g"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The quick
-//             brown fox
-//             jumps over
-//             the lˇazy"},
-//             ["c", "g", "g"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The qˇuick
-//             brown fox
-//             jumps over
-//             the lazy"},
-//             ["c", "g", "g"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             ˇ
-//             brown fox
-//             jumps over
-//             the lazy"},
-//             ["c", "g", "g"],
-//         )
-//         .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_repeated_cj(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         for count in 1..=5 {
-//             cx.assert_binding_matches_all(
-//                 ["c", &count.to_string(), "j"],
-//                 indoc! {"
-//                     ˇThe quˇickˇ browˇn
-//                     ˇ
-//                     ˇfox ˇjumpsˇ-ˇoˇver
-//                     ˇthe lazy dog
-//                     "},
-//             )
-//             .await;
-//         }
-//     }
-
-//     #[gpui::test]
-//     async fn test_repeated_cl(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         for count in 1..=5 {
-//             cx.assert_binding_matches_all(
-//                 ["c", &count.to_string(), "l"],
-//                 indoc! {"
-//                     ˇThe quˇickˇ browˇn
-//                     ˇ
-//                     ˇfox ˇjumpsˇ-ˇoˇver
-//                     ˇthe lazy dog
-//                     "},
-//             )
-//             .await;
-//         }
-//     }
-
-//     #[gpui::test]
-//     async fn test_repeated_cb(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         for count in 1..=5 {
-//             for marked_text in cx.each_marked_position(indoc! {"
-//                 ˇThe quˇickˇ browˇn
-//                 ˇ
-//                 ˇfox ˇjumpsˇ-ˇoˇver
-//                 ˇthe lazy dog
-//                 "})
-//             {
-//                 cx.assert_neovim_compatible(&marked_text, ["c", &count.to_string(), "b"])
-//                     .await;
-//             }
-//         }
-//     }
-
-//     #[gpui::test]
-//     async fn test_repeated_ce(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         for count in 1..=5 {
-//             cx.assert_binding_matches_all(
-//                 ["c", &count.to_string(), "e"],
-//                 indoc! {"
-//                     ˇThe quˇickˇ browˇn
-//                     ˇ
-//                     ˇfox ˇjumpsˇ-ˇoˇver
-//                     ˇthe lazy dog
-//                     "},
-//             )
-//             .await;
-//         }
-//     }
-// }
+#[cfg(test)]
+mod test {
+    use indoc::indoc;
+
+    use crate::test::NeovimBackedTestContext;
+
+    #[gpui::test]
+    async fn test_change_h(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "h"]);
+        cx.assert("Teˇst").await;
+        cx.assert("Tˇest").await;
+        cx.assert("ˇTest").await;
+        cx.assert(indoc! {"
+            Test
+            ˇtest"})
+            .await;
+    }
+
+    #[gpui::test]
+    async fn test_change_backspace(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx)
+            .await
+            .binding(["c", "backspace"]);
+        cx.assert("Teˇst").await;
+        cx.assert("Tˇest").await;
+        cx.assert("ˇTest").await;
+        cx.assert(indoc! {"
+            Test
+            ˇtest"})
+            .await;
+    }
+
+    #[gpui::test]
+    async fn test_change_l(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "l"]);
+        cx.assert("Teˇst").await;
+        cx.assert("Tesˇt").await;
+    }
+
+    #[gpui::test]
+    async fn test_change_w(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "w"]);
+        cx.assert("Teˇst").await;
+        cx.assert("Tˇest test").await;
+        cx.assert("Testˇ  test").await;
+        cx.assert(indoc! {"
+                Test teˇst
+                test"})
+            .await;
+        cx.assert(indoc! {"
+                Test tesˇt
+                test"})
+            .await;
+        cx.assert(indoc! {"
+                Test test
+                ˇ
+                test"})
+            .await;
+
+        let mut cx = cx.binding(["c", "shift-w"]);
+        cx.assert("Test teˇst-test test").await;
+    }
+
+    #[gpui::test]
+    async fn test_change_e(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "e"]);
+        cx.assert("Teˇst Test").await;
+        cx.assert("Tˇest test").await;
+        cx.assert(indoc! {"
+                Test teˇst
+                test"})
+            .await;
+        cx.assert(indoc! {"
+                Test tesˇt
+                test"})
+            .await;
+        cx.assert(indoc! {"
+                Test test
+                ˇ
+                test"})
+            .await;
+
+        let mut cx = cx.binding(["c", "shift-e"]);
+        cx.assert("Test teˇst-test test").await;
+    }
+
+    #[gpui::test]
+    async fn test_change_b(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "b"]);
+        cx.assert("Teˇst Test").await;
+        cx.assert("Test ˇtest").await;
+        cx.assert("Test1 test2 ˇtest3").await;
+        cx.assert(indoc! {"
+                Test test
+                ˇtest"})
+            .await;
+        cx.assert(indoc! {"
+                Test test
+                ˇ
+                test"})
+            .await;
+
+        let mut cx = cx.binding(["c", "shift-b"]);
+        cx.assert("Test test-test ˇtest").await;
+    }
+
+    #[gpui::test]
+    async fn test_change_end_of_line(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "$"]);
+        cx.assert(indoc! {"
+            The qˇuick
+            brown fox"})
+            .await;
+        cx.assert(indoc! {"
+            The quick
+            ˇ
+            brown fox"})
+            .await;
+    }
+
+    #[gpui::test]
+    async fn test_change_0(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The qˇuick
+            brown fox"},
+            ["c", "0"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The quick
+            ˇ
+            brown fox"},
+            ["c", "0"],
+        )
+        .await;
+    }
+
+    #[gpui::test]
+    async fn test_change_k(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The quick
+            brown ˇfox
+            jumps over"},
+            ["c", "k"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The quick
+            brown fox
+            jumps ˇover"},
+            ["c", "k"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The qˇuick
+            brown fox
+            jumps over"},
+            ["c", "k"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            ˇ
+            brown fox
+            jumps over"},
+            ["c", "k"],
+        )
+        .await;
+    }
+
+    #[gpui::test]
+    async fn test_change_j(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The quick
+            brown ˇfox
+            jumps over"},
+            ["c", "j"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The quick
+            brown fox
+            jumps ˇover"},
+            ["c", "j"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The qˇuick
+            brown fox
+            jumps over"},
+            ["c", "j"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The quick
+            brown fox
+            ˇ"},
+            ["c", "j"],
+        )
+        .await;
+    }
+
+    #[gpui::test]
+    async fn test_change_end_of_document(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The quick
+            brownˇ fox
+            jumps over
+            the lazy"},
+            ["c", "shift-g"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The quick
+            brownˇ fox
+            jumps over
+            the lazy"},
+            ["c", "shift-g"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The quick
+            brown fox
+            jumps over
+            the lˇazy"},
+            ["c", "shift-g"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The quick
+            brown fox
+            jumps over
+            ˇ"},
+            ["c", "shift-g"],
+        )
+        .await;
+    }
+
+    #[gpui::test]
+    async fn test_change_gg(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The quick
+            brownˇ fox
+            jumps over
+            the lazy"},
+            ["c", "g", "g"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The quick
+            brown fox
+            jumps over
+            the lˇazy"},
+            ["c", "g", "g"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The qˇuick
+            brown fox
+            jumps over
+            the lazy"},
+            ["c", "g", "g"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            ˇ
+            brown fox
+            jumps over
+            the lazy"},
+            ["c", "g", "g"],
+        )
+        .await;
+    }
+
+    #[gpui::test]
+    async fn test_repeated_cj(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        for count in 1..=5 {
+            cx.assert_binding_matches_all(
+                ["c", &count.to_string(), "j"],
+                indoc! {"
+                    ˇThe quˇickˇ browˇn
+                    ˇ
+                    ˇfox ˇjumpsˇ-ˇoˇver
+                    ˇthe lazy dog
+                    "},
+            )
+            .await;
+        }
+    }
+
+    #[gpui::test]
+    async fn test_repeated_cl(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        for count in 1..=5 {
+            cx.assert_binding_matches_all(
+                ["c", &count.to_string(), "l"],
+                indoc! {"
+                    ˇThe quˇickˇ browˇn
+                    ˇ
+                    ˇfox ˇjumpsˇ-ˇoˇver
+                    ˇthe lazy dog
+                    "},
+            )
+            .await;
+        }
+    }
+
+    #[gpui::test]
+    async fn test_repeated_cb(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        for count in 1..=5 {
+            for marked_text in cx.each_marked_position(indoc! {"
+                ˇThe quˇickˇ browˇn
+                ˇ
+                ˇfox ˇjumpsˇ-ˇoˇver
+                ˇthe lazy dog
+                "})
+            {
+                cx.assert_neovim_compatible(&marked_text, ["c", &count.to_string(), "b"])
+                    .await;
+            }
+        }
+    }
+
+    #[gpui::test]
+    async fn test_repeated_ce(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        for count in 1..=5 {
+            cx.assert_binding_matches_all(
+                ["c", &count.to_string(), "e"],
+                indoc! {"
+                    ˇThe quˇickˇ browˇn
+                    ˇ
+                    ˇfox ˇjumpsˇ-ˇoˇver
+                    ˇthe lazy dog
+                    "},
+            )
+            .await;
+        }
+    }
+}

crates/vim2/src/normal/delete.rs 🔗

@@ -117,359 +117,359 @@ pub fn delete_object(vim: &mut Vim, object: Object, around: bool, cx: &mut Windo
     });
 }
 
-// #[cfg(test)]
-// mod test {
-//     use indoc::indoc;
+#[cfg(test)]
+mod test {
+    use indoc::indoc;
 
-//     use crate::{
-//         state::Mode,
-//         test::{ExemptionFeatures, NeovimBackedTestContext, VimTestContext},
-//     };
+    use crate::{
+        state::Mode,
+        test::{ExemptionFeatures, NeovimBackedTestContext, VimTestContext},
+    };
 
-//     #[gpui::test]
-//     async fn test_delete_h(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "h"]);
-//         cx.assert("Teˇst").await;
-//         cx.assert("Tˇest").await;
-//         cx.assert("ˇTest").await;
-//         cx.assert(indoc! {"
-//             Test
-//             ˇtest"})
-//             .await;
-//     }
+    #[gpui::test]
+    async fn test_delete_h(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "h"]);
+        cx.assert("Teˇst").await;
+        cx.assert("Tˇest").await;
+        cx.assert("ˇTest").await;
+        cx.assert(indoc! {"
+            Test
+            ˇtest"})
+            .await;
+    }
 
-//     #[gpui::test]
-//     async fn test_delete_l(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "l"]);
-//         cx.assert("ˇTest").await;
-//         cx.assert("Teˇst").await;
-//         cx.assert("Tesˇt").await;
-//         cx.assert(indoc! {"
-//                 Tesˇt
-//                 test"})
-//             .await;
-//     }
+    #[gpui::test]
+    async fn test_delete_l(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "l"]);
+        cx.assert("ˇTest").await;
+        cx.assert("Teˇst").await;
+        cx.assert("Tesˇt").await;
+        cx.assert(indoc! {"
+                Tesˇt
+                test"})
+            .await;
+    }
 
-//     #[gpui::test]
-//     async fn test_delete_w(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             Test tesˇt
-//                 test"},
-//             ["d", "w"],
-//         )
-//         .await;
+    #[gpui::test]
+    async fn test_delete_w(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            Test tesˇt
+                test"},
+            ["d", "w"],
+        )
+        .await;
 
-//         cx.assert_neovim_compatible("Teˇst", ["d", "w"]).await;
-//         cx.assert_neovim_compatible("Tˇest test", ["d", "w"]).await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             Test teˇst
-//             test"},
-//             ["d", "w"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             Test tesˇt
-//             test"},
-//             ["d", "w"],
-//         )
-//         .await;
+        cx.assert_neovim_compatible("Teˇst", ["d", "w"]).await;
+        cx.assert_neovim_compatible("Tˇest test", ["d", "w"]).await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            Test teˇst
+            test"},
+            ["d", "w"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            Test tesˇt
+            test"},
+            ["d", "w"],
+        )
+        .await;
 
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             Test test
-//             ˇ
-//             test"},
-//             ["d", "w"],
-//         )
-//         .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            Test test
+            ˇ
+            test"},
+            ["d", "w"],
+        )
+        .await;
 
-//         let mut cx = cx.binding(["d", "shift-w"]);
-//         cx.assert_neovim_compatible("Test teˇst-test test", ["d", "shift-w"])
-//             .await;
-//     }
+        let mut cx = cx.binding(["d", "shift-w"]);
+        cx.assert_neovim_compatible("Test teˇst-test test", ["d", "shift-w"])
+            .await;
+    }
 
-//     #[gpui::test]
-//     async fn test_delete_next_word_end(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "e"]);
-//         // cx.assert("Teˇst Test").await;
-//         // cx.assert("Tˇest test").await;
-//         cx.assert(indoc! {"
-//             Test teˇst
-//             test"})
-//             .await;
-//         cx.assert(indoc! {"
-//             Test tesˇt
-//             test"})
-//             .await;
-//         cx.assert_exempted(
-//             indoc! {"
-//             Test test
-//             ˇ
-//             test"},
-//             ExemptionFeatures::OperatorLastNewlineRemains,
-//         )
-//         .await;
+    #[gpui::test]
+    async fn test_delete_next_word_end(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "e"]);
+        // cx.assert("Teˇst Test").await;
+        // cx.assert("Tˇest test").await;
+        cx.assert(indoc! {"
+            Test teˇst
+            test"})
+            .await;
+        cx.assert(indoc! {"
+            Test tesˇt
+            test"})
+            .await;
+        cx.assert_exempted(
+            indoc! {"
+            Test test
+            ˇ
+            test"},
+            ExemptionFeatures::OperatorLastNewlineRemains,
+        )
+        .await;
 
-//         let mut cx = cx.binding(["d", "shift-e"]);
-//         cx.assert("Test teˇst-test test").await;
-//     }
+        let mut cx = cx.binding(["d", "shift-e"]);
+        cx.assert("Test teˇst-test test").await;
+    }
 
-//     #[gpui::test]
-//     async fn test_delete_b(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "b"]);
-//         cx.assert("Teˇst Test").await;
-//         cx.assert("Test ˇtest").await;
-//         cx.assert("Test1 test2 ˇtest3").await;
-//         cx.assert(indoc! {"
-//             Test test
-//             ˇtest"})
-//             .await;
-//         cx.assert(indoc! {"
-//             Test test
-//             ˇ
-//             test"})
-//             .await;
+    #[gpui::test]
+    async fn test_delete_b(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "b"]);
+        cx.assert("Teˇst Test").await;
+        cx.assert("Test ˇtest").await;
+        cx.assert("Test1 test2 ˇtest3").await;
+        cx.assert(indoc! {"
+            Test test
+            ˇtest"})
+            .await;
+        cx.assert(indoc! {"
+            Test test
+            ˇ
+            test"})
+            .await;
 
-//         let mut cx = cx.binding(["d", "shift-b"]);
-//         cx.assert("Test test-test ˇtest").await;
-//     }
+        let mut cx = cx.binding(["d", "shift-b"]);
+        cx.assert("Test test-test ˇtest").await;
+    }
 
-//     #[gpui::test]
-//     async fn test_delete_end_of_line(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "$"]);
-//         cx.assert(indoc! {"
-//             The qˇuick
-//             brown fox"})
-//             .await;
-//         cx.assert(indoc! {"
-//             The quick
-//             ˇ
-//             brown fox"})
-//             .await;
-//     }
+    #[gpui::test]
+    async fn test_delete_end_of_line(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "$"]);
+        cx.assert(indoc! {"
+            The qˇuick
+            brown fox"})
+            .await;
+        cx.assert(indoc! {"
+            The quick
+            ˇ
+            brown fox"})
+            .await;
+    }
 
-//     #[gpui::test]
-//     async fn test_delete_0(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "0"]);
-//         cx.assert(indoc! {"
-//             The qˇuick
-//             brown fox"})
-//             .await;
-//         cx.assert(indoc! {"
-//             The quick
-//             ˇ
-//             brown fox"})
-//             .await;
-//     }
+    #[gpui::test]
+    async fn test_delete_0(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "0"]);
+        cx.assert(indoc! {"
+            The qˇuick
+            brown fox"})
+            .await;
+        cx.assert(indoc! {"
+            The quick
+            ˇ
+            brown fox"})
+            .await;
+    }
 
-//     #[gpui::test]
-//     async fn test_delete_k(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "k"]);
-//         cx.assert(indoc! {"
-//             The quick
-//             brown ˇfox
-//             jumps over"})
-//             .await;
-//         cx.assert(indoc! {"
-//             The quick
-//             brown fox
-//             jumps ˇover"})
-//             .await;
-//         cx.assert(indoc! {"
-//             The qˇuick
-//             brown fox
-//             jumps over"})
-//             .await;
-//         cx.assert(indoc! {"
-//             ˇbrown fox
-//             jumps over"})
-//             .await;
-//     }
+    #[gpui::test]
+    async fn test_delete_k(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "k"]);
+        cx.assert(indoc! {"
+            The quick
+            brown ˇfox
+            jumps over"})
+            .await;
+        cx.assert(indoc! {"
+            The quick
+            brown fox
+            jumps ˇover"})
+            .await;
+        cx.assert(indoc! {"
+            The qˇuick
+            brown fox
+            jumps over"})
+            .await;
+        cx.assert(indoc! {"
+            ˇbrown fox
+            jumps over"})
+            .await;
+    }
 
-//     #[gpui::test]
-//     async fn test_delete_j(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "j"]);
-//         cx.assert(indoc! {"
-//             The quick
-//             brown ˇfox
-//             jumps over"})
-//             .await;
-//         cx.assert(indoc! {"
-//             The quick
-//             brown fox
-//             jumps ˇover"})
-//             .await;
-//         cx.assert(indoc! {"
-//             The qˇuick
-//             brown fox
-//             jumps over"})
-//             .await;
-//         cx.assert(indoc! {"
-//             The quick
-//             brown fox
-//             ˇ"})
-//             .await;
-//     }
+    #[gpui::test]
+    async fn test_delete_j(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "j"]);
+        cx.assert(indoc! {"
+            The quick
+            brown ˇfox
+            jumps over"})
+            .await;
+        cx.assert(indoc! {"
+            The quick
+            brown fox
+            jumps ˇover"})
+            .await;
+        cx.assert(indoc! {"
+            The qˇuick
+            brown fox
+            jumps over"})
+            .await;
+        cx.assert(indoc! {"
+            The quick
+            brown fox
+            ˇ"})
+            .await;
+    }
 
-//     #[gpui::test]
-//     async fn test_delete_end_of_document(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The quick
-//             brownˇ fox
-//             jumps over
-//             the lazy"},
-//             ["d", "shift-g"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The quick
-//             brownˇ fox
-//             jumps over
-//             the lazy"},
-//             ["d", "shift-g"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The quick
-//             brown fox
-//             jumps over
-//             the lˇazy"},
-//             ["d", "shift-g"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The quick
-//             brown fox
-//             jumps over
-//             ˇ"},
-//             ["d", "shift-g"],
-//         )
-//         .await;
-//     }
+    #[gpui::test]
+    async fn test_delete_end_of_document(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The quick
+            brownˇ fox
+            jumps over
+            the lazy"},
+            ["d", "shift-g"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The quick
+            brownˇ fox
+            jumps over
+            the lazy"},
+            ["d", "shift-g"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The quick
+            brown fox
+            jumps over
+            the lˇazy"},
+            ["d", "shift-g"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The quick
+            brown fox
+            jumps over
+            ˇ"},
+            ["d", "shift-g"],
+        )
+        .await;
+    }
 
-//     #[gpui::test]
-//     async fn test_delete_gg(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx)
-//             .await
-//             .binding(["d", "g", "g"]);
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The quick
-//             brownˇ fox
-//             jumps over
-//             the lazy"},
-//             ["d", "g", "g"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The quick
-//             brown fox
-//             jumps over
-//             the lˇazy"},
-//             ["d", "g", "g"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             The qˇuick
-//             brown fox
-//             jumps over
-//             the lazy"},
-//             ["d", "g", "g"],
-//         )
-//         .await;
-//         cx.assert_neovim_compatible(
-//             indoc! {"
-//             ˇ
-//             brown fox
-//             jumps over
-//             the lazy"},
-//             ["d", "g", "g"],
-//         )
-//         .await;
-//     }
+    #[gpui::test]
+    async fn test_delete_gg(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx)
+            .await
+            .binding(["d", "g", "g"]);
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The quick
+            brownˇ fox
+            jumps over
+            the lazy"},
+            ["d", "g", "g"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The quick
+            brown fox
+            jumps over
+            the lˇazy"},
+            ["d", "g", "g"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            The qˇuick
+            brown fox
+            jumps over
+            the lazy"},
+            ["d", "g", "g"],
+        )
+        .await;
+        cx.assert_neovim_compatible(
+            indoc! {"
+            ˇ
+            brown fox
+            jumps over
+            the lazy"},
+            ["d", "g", "g"],
+        )
+        .await;
+    }
 
-//     #[gpui::test]
-//     async fn test_cancel_delete_operator(cx: &mut gpui::TestAppContext) {
-//         let mut cx = VimTestContext::new(cx, true).await;
-//         cx.set_state(
-//             indoc! {"
-//                 The quick brown
-//                 fox juˇmps over
-//                 the lazy dog"},
-//             Mode::Normal,
-//         );
+    #[gpui::test]
+    async fn test_cancel_delete_operator(cx: &mut gpui::TestAppContext) {
+        let mut cx = VimTestContext::new(cx, true).await;
+        cx.set_state(
+            indoc! {"
+                The quick brown
+                fox juˇmps over
+                the lazy dog"},
+            Mode::Normal,
+        );
 
-//         // Canceling operator twice reverts to normal mode with no active operator
-//         cx.simulate_keystrokes(["d", "escape", "k"]);
-//         assert_eq!(cx.active_operator(), None);
-//         assert_eq!(cx.mode(), Mode::Normal);
-//         cx.assert_editor_state(indoc! {"
-//             The quˇick brown
-//             fox jumps over
-//             the lazy dog"});
-//     }
+        // Canceling operator twice reverts to normal mode with no active operator
+        cx.simulate_keystrokes(["d", "escape", "k"]);
+        assert_eq!(cx.active_operator(), None);
+        assert_eq!(cx.mode(), Mode::Normal);
+        cx.assert_editor_state(indoc! {"
+            The quˇick brown
+            fox jumps over
+            the lazy dog"});
+    }
 
-//     #[gpui::test]
-//     async fn test_unbound_command_cancels_pending_operator(cx: &mut gpui::TestAppContext) {
-//         let mut cx = VimTestContext::new(cx, true).await;
-//         cx.set_state(
-//             indoc! {"
-//                 The quick brown
-//                 fox juˇmps over
-//                 the lazy dog"},
-//             Mode::Normal,
-//         );
+    #[gpui::test]
+    async fn test_unbound_command_cancels_pending_operator(cx: &mut gpui::TestAppContext) {
+        let mut cx = VimTestContext::new(cx, true).await;
+        cx.set_state(
+            indoc! {"
+                The quick brown
+                fox juˇmps over
+                the lazy dog"},
+            Mode::Normal,
+        );
 
-//         // Canceling operator twice reverts to normal mode with no active operator
-//         cx.simulate_keystrokes(["d", "y"]);
-//         assert_eq!(cx.active_operator(), None);
-//         assert_eq!(cx.mode(), Mode::Normal);
-//     }
+        // Canceling operator twice reverts to normal mode with no active operator
+        cx.simulate_keystrokes(["d", "y"]);
+        assert_eq!(cx.active_operator(), None);
+        assert_eq!(cx.mode(), Mode::Normal);
+    }
 
-//     #[gpui::test]
-//     async fn test_delete_with_counts(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-//         cx.set_shared_state(indoc! {"
-//                 The ˇquick brown
-//                 fox jumps over
-//                 the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["d", "2", "d"]).await;
-//         cx.assert_shared_state(indoc! {"
-//         the ˇlazy dog"})
-//             .await;
+    #[gpui::test]
+    async fn test_delete_with_counts(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+        cx.set_shared_state(indoc! {"
+                The ˇquick brown
+                fox jumps over
+                the lazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["d", "2", "d"]).await;
+        cx.assert_shared_state(indoc! {"
+        the ˇlazy dog"})
+            .await;
 
-//         cx.set_shared_state(indoc! {"
-//                 The ˇquick brown
-//                 fox jumps over
-//                 the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["2", "d", "d"]).await;
-//         cx.assert_shared_state(indoc! {"
-//         the ˇlazy dog"})
-//             .await;
+        cx.set_shared_state(indoc! {"
+                The ˇquick brown
+                fox jumps over
+                the lazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["2", "d", "d"]).await;
+        cx.assert_shared_state(indoc! {"
+        the ˇlazy dog"})
+            .await;
 
-//         cx.set_shared_state(indoc! {"
-//                 The ˇquick brown
-//                 fox jumps over
-//                 the moon,
-//                 a star, and
-//                 the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["2", "d", "2", "d"]).await;
-//         cx.assert_shared_state(indoc! {"
-//         the ˇlazy dog"})
-//             .await;
-//     }
-// }
+        cx.set_shared_state(indoc! {"
+                The ˇquick brown
+                fox jumps over
+                the moon,
+                a star, and
+                the lazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["2", "d", "2", "d"]).await;
+        cx.assert_shared_state(indoc! {"
+        the ˇlazy dog"})
+            .await;
+    }
+}

crates/vim2/src/normal/increment.rs 🔗

@@ -173,106 +173,106 @@ fn find_number(
     }
 }
 
-// #[cfg(test)]
-// mod test {
-//     use indoc::indoc;
+#[cfg(test)]
+mod test {
+    use indoc::indoc;
 
-//     use crate::test::NeovimBackedTestContext;
+    use crate::test::NeovimBackedTestContext;
 
-//     #[gpui::test]
-//     async fn test_increment(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
+    #[gpui::test]
+    async fn test_increment(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
 
-//         cx.set_shared_state(indoc! {"
-//             1ˇ2
-//             "})
-//             .await;
+        cx.set_shared_state(indoc! {"
+            1ˇ2
+            "})
+            .await;
 
-//         cx.simulate_shared_keystrokes(["ctrl-a"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             1ˇ3
-//             "})
-//             .await;
-//         cx.simulate_shared_keystrokes(["ctrl-x"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             1ˇ2
-//             "})
-//             .await;
+        cx.simulate_shared_keystrokes(["ctrl-a"]).await;
+        cx.assert_shared_state(indoc! {"
+            1ˇ3
+            "})
+            .await;
+        cx.simulate_shared_keystrokes(["ctrl-x"]).await;
+        cx.assert_shared_state(indoc! {"
+            1ˇ2
+            "})
+            .await;
 
-//         cx.simulate_shared_keystrokes(["9", "9", "ctrl-a"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             11ˇ1
-//             "})
-//             .await;
-//         cx.simulate_shared_keystrokes(["1", "1", "1", "ctrl-x"])
-//             .await;
-//         cx.assert_shared_state(indoc! {"
-//             ˇ0
-//             "})
-//             .await;
-//         cx.simulate_shared_keystrokes(["."]).await;
-//         cx.assert_shared_state(indoc! {"
-//             -11ˇ1
-//             "})
-//             .await;
-//     }
+        cx.simulate_shared_keystrokes(["9", "9", "ctrl-a"]).await;
+        cx.assert_shared_state(indoc! {"
+            11ˇ1
+            "})
+            .await;
+        cx.simulate_shared_keystrokes(["1", "1", "1", "ctrl-x"])
+            .await;
+        cx.assert_shared_state(indoc! {"
+            ˇ0
+            "})
+            .await;
+        cx.simulate_shared_keystrokes(["."]).await;
+        cx.assert_shared_state(indoc! {"
+            -11ˇ1
+            "})
+            .await;
+    }
 
-//     #[gpui::test]
-//     async fn test_increment_radix(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
+    #[gpui::test]
+    async fn test_increment_radix(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
 
-//         cx.assert_matches_neovim("ˇ total: 0xff", ["ctrl-a"], " total: 0x10ˇ0")
-//             .await;
-//         cx.assert_matches_neovim("ˇ total: 0xff", ["ctrl-x"], " total: 0xfˇe")
-//             .await;
-//         cx.assert_matches_neovim("ˇ total: 0xFF", ["ctrl-x"], " total: 0xFˇE")
-//             .await;
-//         cx.assert_matches_neovim("(ˇ0b10f)", ["ctrl-a"], "(0b1ˇ1f)")
-//             .await;
-//         cx.assert_matches_neovim("ˇ-1", ["ctrl-a"], "ˇ0").await;
-//         cx.assert_matches_neovim("banˇana", ["ctrl-a"], "banˇana")
-//             .await;
-//     }
+        cx.assert_matches_neovim("ˇ total: 0xff", ["ctrl-a"], " total: 0x10ˇ0")
+            .await;
+        cx.assert_matches_neovim("ˇ total: 0xff", ["ctrl-x"], " total: 0xfˇe")
+            .await;
+        cx.assert_matches_neovim("ˇ total: 0xFF", ["ctrl-x"], " total: 0xFˇE")
+            .await;
+        cx.assert_matches_neovim("(ˇ0b10f)", ["ctrl-a"], "(0b1ˇ1f)")
+            .await;
+        cx.assert_matches_neovim("ˇ-1", ["ctrl-a"], "ˇ0").await;
+        cx.assert_matches_neovim("banˇana", ["ctrl-a"], "banˇana")
+            .await;
+    }
 
-//     #[gpui::test]
-//     async fn test_increment_steps(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
+    #[gpui::test]
+    async fn test_increment_steps(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
 
-//         cx.set_shared_state(indoc! {"
-//             ˇ1
-//             1
-//             1  2
-//             1
-//             1"})
-//             .await;
+        cx.set_shared_state(indoc! {"
+            ˇ1
+            1
+            1  2
+            1
+            1"})
+            .await;
 
-//         cx.simulate_shared_keystrokes(["j", "v", "shift-g", "g", "ctrl-a"])
-//             .await;
-//         cx.assert_shared_state(indoc! {"
-//             1
-//             ˇ2
-//             3  2
-//             4
-//             5"})
-//             .await;
+        cx.simulate_shared_keystrokes(["j", "v", "shift-g", "g", "ctrl-a"])
+            .await;
+        cx.assert_shared_state(indoc! {"
+            1
+            ˇ2
+            3  2
+            4
+            5"})
+            .await;
 
-//         cx.simulate_shared_keystrokes(["shift-g", "ctrl-v", "g", "g"])
-//             .await;
-//         cx.assert_shared_state(indoc! {"
-//             «1ˇ»
-//             «2ˇ»
-//             «3ˇ»  2
-//             «4ˇ»
-//             «5ˇ»"})
-//             .await;
+        cx.simulate_shared_keystrokes(["shift-g", "ctrl-v", "g", "g"])
+            .await;
+        cx.assert_shared_state(indoc! {"
+            «1ˇ»
+            «2ˇ»
+            «3ˇ»  2
+            «4ˇ»
+            «5ˇ»"})
+            .await;
 
-//         cx.simulate_shared_keystrokes(["g", "ctrl-x"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             ˇ0
-//             0
-//             0  2
-//             0
-//             0"})
-//             .await;
-//     }
-// }
+        cx.simulate_shared_keystrokes(["g", "ctrl-x"]).await;
+        cx.assert_shared_state(indoc! {"
+            ˇ0
+            0
+            0  2
+            0
+            0"})
+            .await;
+    }
+}

crates/vim2/src/normal/paste.rs 🔗

@@ -197,280 +197,280 @@ fn paste(_: &mut Workspace, action: &Paste, cx: &mut ViewContext<Workspace>) {
     });
 }
 
-// #[cfg(test)]
-// mod test {
-//     use crate::{
-//         state::Mode,
-//         test::{NeovimBackedTestContext, VimTestContext},
-//     };
-//     use indoc::indoc;
-
-//     #[gpui::test]
-//     async fn test_paste(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         // single line
-//         cx.set_shared_state(indoc! {"
-//             The quick brown
-//             fox ˇjumps over
-//             the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["v", "w", "y"]).await;
-//         cx.assert_shared_clipboard("jumps o").await;
-//         cx.set_shared_state(indoc! {"
-//             The quick brown
-//             fox jumps oveˇr
-//             the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystroke("p").await;
-//         cx.assert_shared_state(indoc! {"
-//             The quick brown
-//             fox jumps overjumps ˇo
-//             the lazy dog"})
-//             .await;
-
-//         cx.set_shared_state(indoc! {"
-//             The quick brown
-//             fox jumps oveˇr
-//             the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystroke("shift-p").await;
-//         cx.assert_shared_state(indoc! {"
-//             The quick brown
-//             fox jumps ovejumps ˇor
-//             the lazy dog"})
-//             .await;
-
-//         // line mode
-//         cx.set_shared_state(indoc! {"
-//             The quick brown
-//             fox juˇmps over
-//             the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["d", "d"]).await;
-//         cx.assert_shared_clipboard("fox jumps over\n").await;
-//         cx.assert_shared_state(indoc! {"
-//             The quick brown
-//             the laˇzy dog"})
-//             .await;
-//         cx.simulate_shared_keystroke("p").await;
-//         cx.assert_shared_state(indoc! {"
-//             The quick brown
-//             the lazy dog
-//             ˇfox jumps over"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["k", "shift-p"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             The quick brown
-//             ˇfox jumps over
-//             the lazy dog
-//             fox jumps over"})
-//             .await;
-
-//         // multiline, cursor to first character of pasted text.
-//         cx.set_shared_state(indoc! {"
-//             The quick brown
-//             fox jumps ˇover
-//             the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["v", "j", "y"]).await;
-//         cx.assert_shared_clipboard("over\nthe lazy do").await;
-
-//         cx.simulate_shared_keystroke("p").await;
-//         cx.assert_shared_state(indoc! {"
-//             The quick brown
-//             fox jumps oˇover
-//             the lazy dover
-//             the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["u", "shift-p"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             The quick brown
-//             fox jumps ˇover
-//             the lazy doover
-//             the lazy dog"})
-//             .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_paste_visual(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         // copy in visual mode
-//         cx.set_shared_state(indoc! {"
-//                 The quick brown
-//                 fox jˇumps over
-//                 the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["v", "i", "w", "y"]).await;
-//         cx.assert_shared_state(indoc! {"
-//                 The quick brown
-//                 fox ˇjumps over
-//                 the lazy dog"})
-//             .await;
-//         // paste in visual mode
-//         cx.simulate_shared_keystrokes(["w", "v", "i", "w", "p"])
-//             .await;
-//         cx.assert_shared_state(indoc! {"
-//                 The quick brown
-//                 fox jumps jumpˇs
-//                 the lazy dog"})
-//             .await;
-//         cx.assert_shared_clipboard("over").await;
-//         // paste in visual line mode
-//         cx.simulate_shared_keystrokes(["up", "shift-v", "shift-p"])
-//             .await;
-//         cx.assert_shared_state(indoc! {"
-//             ˇover
-//             fox jumps jumps
-//             the lazy dog"})
-//             .await;
-//         cx.assert_shared_clipboard("over").await;
-//         // paste in visual block mode
-//         cx.simulate_shared_keystrokes(["ctrl-v", "down", "down", "p"])
-//             .await;
-//         cx.assert_shared_state(indoc! {"
-//             oveˇrver
-//             overox jumps jumps
-//             overhe lazy dog"})
-//             .await;
-
-//         // copy in visual line mode
-//         cx.set_shared_state(indoc! {"
-//                 The quick brown
-//                 fox juˇmps over
-//                 the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["shift-v", "d"]).await;
-//         cx.assert_shared_state(indoc! {"
-//                 The quick brown
-//                 the laˇzy dog"})
-//             .await;
-//         // paste in visual mode
-//         cx.simulate_shared_keystrokes(["v", "i", "w", "p"]).await;
-//         cx.assert_shared_state(
-//             &indoc! {"
-//                 The quick brown
-//                 the_
-//                 ˇfox jumps over
-//                 _dog"}
-//             .replace("_", " "), // Hack for trailing whitespace
-//         )
-//         .await;
-//         cx.assert_shared_clipboard("lazy").await;
-//         cx.set_shared_state(indoc! {"
-//             The quick brown
-//             fox juˇmps over
-//             the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["shift-v", "d"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             The quick brown
-//             the laˇzy dog"})
-//             .await;
-//         // paste in visual line mode
-//         cx.simulate_shared_keystrokes(["k", "shift-v", "p"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             ˇfox jumps over
-//             the lazy dog"})
-//             .await;
-//         cx.assert_shared_clipboard("The quick brown\n").await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_paste_visual_block(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-//         // copy in visual block mode
-//         cx.set_shared_state(indoc! {"
-//             The ˇquick brown
-//             fox jumps over
-//             the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["ctrl-v", "2", "j", "y"])
-//             .await;
-//         cx.assert_shared_clipboard("q\nj\nl").await;
-//         cx.simulate_shared_keystrokes(["p"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             The qˇquick brown
-//             fox jjumps over
-//             the llazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["v", "i", "w", "shift-p"])
-//             .await;
-//         cx.assert_shared_state(indoc! {"
-//             The ˇq brown
-//             fox jjjumps over
-//             the lllazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["v", "i", "w", "shift-p"])
-//             .await;
-
-//         cx.set_shared_state(indoc! {"
-//             The ˇquick brown
-//             fox jumps over
-//             the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["ctrl-v", "j", "y"]).await;
-//         cx.assert_shared_clipboard("q\nj").await;
-//         cx.simulate_shared_keystrokes(["l", "ctrl-v", "2", "j", "shift-p"])
-//             .await;
-//         cx.assert_shared_state(indoc! {"
-//             The qˇqick brown
-//             fox jjmps over
-//             the lzy dog"})
-//             .await;
-
-//         cx.simulate_shared_keystrokes(["shift-v", "p"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             ˇq
-//             j
-//             fox jjmps over
-//             the lzy dog"})
-//             .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_paste_indent(cx: &mut gpui::TestAppContext) {
-//         let mut cx = VimTestContext::new_typescript(cx).await;
-
-//         cx.set_state(
-//             indoc! {"
-//             class A {ˇ
-//             }
-//         "},
-//             Mode::Normal,
-//         );
-//         cx.simulate_keystrokes(["o", "a", "(", ")", "{", "escape"]);
-//         cx.assert_state(
-//             indoc! {"
-//             class A {
-//                 a()ˇ{}
-//             }
-//             "},
-//             Mode::Normal,
-//         );
-//         // cursor goes to the first non-blank character in the line;
-//         cx.simulate_keystrokes(["y", "y", "p"]);
-//         cx.assert_state(
-//             indoc! {"
-//             class A {
-//                 a(){}
-//                 ˇa(){}
-//             }
-//             "},
-//             Mode::Normal,
-//         );
-//         // indentation is preserved when pasting
-//         cx.simulate_keystrokes(["u", "shift-v", "up", "y", "shift-p"]);
-//         cx.assert_state(
-//             indoc! {"
-//                 ˇclass A {
-//                     a(){}
-//                 class A {
-//                     a(){}
-//                 }
-//                 "},
-//             Mode::Normal,
-//         );
-//     }
-// }
+#[cfg(test)]
+mod test {
+    use crate::{
+        state::Mode,
+        test::{NeovimBackedTestContext, VimTestContext},
+    };
+    use indoc::indoc;
+
+    #[gpui::test]
+    async fn test_paste(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        // single line
+        cx.set_shared_state(indoc! {"
+            The quick brown
+            fox ˇjumps over
+            the lazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["v", "w", "y"]).await;
+        cx.assert_shared_clipboard("jumps o").await;
+        cx.set_shared_state(indoc! {"
+            The quick brown
+            fox jumps oveˇr
+            the lazy dog"})
+            .await;
+        cx.simulate_shared_keystroke("p").await;
+        cx.assert_shared_state(indoc! {"
+            The quick brown
+            fox jumps overjumps ˇo
+            the lazy dog"})
+            .await;
+
+        cx.set_shared_state(indoc! {"
+            The quick brown
+            fox jumps oveˇr
+            the lazy dog"})
+            .await;
+        cx.simulate_shared_keystroke("shift-p").await;
+        cx.assert_shared_state(indoc! {"
+            The quick brown
+            fox jumps ovejumps ˇor
+            the lazy dog"})
+            .await;
+
+        // line mode
+        cx.set_shared_state(indoc! {"
+            The quick brown
+            fox juˇmps over
+            the lazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["d", "d"]).await;
+        cx.assert_shared_clipboard("fox jumps over\n").await;
+        cx.assert_shared_state(indoc! {"
+            The quick brown
+            the laˇzy dog"})
+            .await;
+        cx.simulate_shared_keystroke("p").await;
+        cx.assert_shared_state(indoc! {"
+            The quick brown
+            the lazy dog
+            ˇfox jumps over"})
+            .await;
+        cx.simulate_shared_keystrokes(["k", "shift-p"]).await;
+        cx.assert_shared_state(indoc! {"
+            The quick brown
+            ˇfox jumps over
+            the lazy dog
+            fox jumps over"})
+            .await;
+
+        // multiline, cursor to first character of pasted text.
+        cx.set_shared_state(indoc! {"
+            The quick brown
+            fox jumps ˇover
+            the lazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["v", "j", "y"]).await;
+        cx.assert_shared_clipboard("over\nthe lazy do").await;
+
+        cx.simulate_shared_keystroke("p").await;
+        cx.assert_shared_state(indoc! {"
+            The quick brown
+            fox jumps oˇover
+            the lazy dover
+            the lazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["u", "shift-p"]).await;
+        cx.assert_shared_state(indoc! {"
+            The quick brown
+            fox jumps ˇover
+            the lazy doover
+            the lazy dog"})
+            .await;
+    }
+
+    #[gpui::test]
+    async fn test_paste_visual(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        // copy in visual mode
+        cx.set_shared_state(indoc! {"
+                The quick brown
+                fox jˇumps over
+                the lazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["v", "i", "w", "y"]).await;
+        cx.assert_shared_state(indoc! {"
+                The quick brown
+                fox ˇjumps over
+                the lazy dog"})
+            .await;
+        // paste in visual mode
+        cx.simulate_shared_keystrokes(["w", "v", "i", "w", "p"])
+            .await;
+        cx.assert_shared_state(indoc! {"
+                The quick brown
+                fox jumps jumpˇs
+                the lazy dog"})
+            .await;
+        cx.assert_shared_clipboard("over").await;
+        // paste in visual line mode
+        cx.simulate_shared_keystrokes(["up", "shift-v", "shift-p"])
+            .await;
+        cx.assert_shared_state(indoc! {"
+            ˇover
+            fox jumps jumps
+            the lazy dog"})
+            .await;
+        cx.assert_shared_clipboard("over").await;
+        // paste in visual block mode
+        cx.simulate_shared_keystrokes(["ctrl-v", "down", "down", "p"])
+            .await;
+        cx.assert_shared_state(indoc! {"
+            oveˇrver
+            overox jumps jumps
+            overhe lazy dog"})
+            .await;
+
+        // copy in visual line mode
+        cx.set_shared_state(indoc! {"
+                The quick brown
+                fox juˇmps over
+                the lazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["shift-v", "d"]).await;
+        cx.assert_shared_state(indoc! {"
+                The quick brown
+                the laˇzy dog"})
+            .await;
+        // paste in visual mode
+        cx.simulate_shared_keystrokes(["v", "i", "w", "p"]).await;
+        cx.assert_shared_state(
+            &indoc! {"
+                The quick brown
+                the_
+                ˇfox jumps over
+                _dog"}
+            .replace("_", " "), // Hack for trailing whitespace
+        )
+        .await;
+        cx.assert_shared_clipboard("lazy").await;
+        cx.set_shared_state(indoc! {"
+            The quick brown
+            fox juˇmps over
+            the lazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["shift-v", "d"]).await;
+        cx.assert_shared_state(indoc! {"
+            The quick brown
+            the laˇzy dog"})
+            .await;
+        // paste in visual line mode
+        cx.simulate_shared_keystrokes(["k", "shift-v", "p"]).await;
+        cx.assert_shared_state(indoc! {"
+            ˇfox jumps over
+            the lazy dog"})
+            .await;
+        cx.assert_shared_clipboard("The quick brown\n").await;
+    }
+
+    #[gpui::test]
+    async fn test_paste_visual_block(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+        // copy in visual block mode
+        cx.set_shared_state(indoc! {"
+            The ˇquick brown
+            fox jumps over
+            the lazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["ctrl-v", "2", "j", "y"])
+            .await;
+        cx.assert_shared_clipboard("q\nj\nl").await;
+        cx.simulate_shared_keystrokes(["p"]).await;
+        cx.assert_shared_state(indoc! {"
+            The qˇquick brown
+            fox jjumps over
+            the llazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["v", "i", "w", "shift-p"])
+            .await;
+        cx.assert_shared_state(indoc! {"
+            The ˇq brown
+            fox jjjumps over
+            the lllazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["v", "i", "w", "shift-p"])
+            .await;
+
+        cx.set_shared_state(indoc! {"
+            The ˇquick brown
+            fox jumps over
+            the lazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["ctrl-v", "j", "y"]).await;
+        cx.assert_shared_clipboard("q\nj").await;
+        cx.simulate_shared_keystrokes(["l", "ctrl-v", "2", "j", "shift-p"])
+            .await;
+        cx.assert_shared_state(indoc! {"
+            The qˇqick brown
+            fox jjmps over
+            the lzy dog"})
+            .await;
+
+        cx.simulate_shared_keystrokes(["shift-v", "p"]).await;
+        cx.assert_shared_state(indoc! {"
+            ˇq
+            j
+            fox jjmps over
+            the lzy dog"})
+            .await;
+    }
+
+    #[gpui::test]
+    async fn test_paste_indent(cx: &mut gpui::TestAppContext) {
+        let mut cx = VimTestContext::new_typescript(cx).await;
+
+        cx.set_state(
+            indoc! {"
+            class A {ˇ
+            }
+        "},
+            Mode::Normal,
+        );
+        cx.simulate_keystrokes(["o", "a", "(", ")", "{", "escape"]);
+        cx.assert_state(
+            indoc! {"
+            class A {
+                a()ˇ{}
+            }
+            "},
+            Mode::Normal,
+        );
+        // cursor goes to the first non-blank character in the line;
+        cx.simulate_keystrokes(["y", "y", "p"]);
+        cx.assert_state(
+            indoc! {"
+            class A {
+                a(){}
+                ˇa(){}
+            }
+            "},
+            Mode::Normal,
+        );
+        // indentation is preserved when pasting
+        cx.simulate_keystrokes(["u", "shift-v", "up", "y", "shift-p"]);
+        cx.assert_state(
+            indoc! {"
+                ˇclass A {
+                    a(){}
+                class A {
+                    a(){}
+                }
+                "},
+            Mode::Normal,
+        );
+    }
+}

crates/vim2/src/normal/repeat.rs 🔗

@@ -196,328 +196,301 @@ pub(crate) fn repeat(cx: &mut WindowContext, from_insert_mode: bool) {
     .detach_and_log_err(cx);
 }
 
-// #[cfg(test)]
-// mod test {
-//     use std::sync::Arc;
-
-//     use editor::test::editor_lsp_test_context::EditorLspTestContext;
-//     use futures::StreamExt;
-//     use indoc::indoc;
-
-//     use gpui::{executor::Deterministic, View};
-
-//     use crate::{
-//         state::Mode,
-//         test::{NeovimBackedTestContext, VimTestContext},
-//     };
-
-//     #[gpui::test]
-//     async fn test_dot_repeat(deterministic: Arc<Deterministic>, cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         // "o"
-//         cx.set_shared_state("ˇhello").await;
-//         cx.simulate_shared_keystrokes(["o", "w", "o", "r", "l", "d", "escape"])
-//             .await;
-//         cx.assert_shared_state("hello\nworlˇd").await;
-//         cx.simulate_shared_keystrokes(["."]).await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state("hello\nworld\nworlˇd").await;
-
-//         // "d"
-//         cx.simulate_shared_keystrokes(["^", "d", "f", "o"]).await;
-//         cx.simulate_shared_keystrokes(["g", "g", "."]).await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state("ˇ\nworld\nrld").await;
-
-//         // "p" (note that it pastes the current clipboard)
-//         cx.simulate_shared_keystrokes(["j", "y", "y", "p"]).await;
-//         cx.simulate_shared_keystrokes(["shift-g", "y", "y", "."])
-//             .await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state("\nworld\nworld\nrld\nˇrld").await;
-
-//         // "~" (note that counts apply to the action taken, not . itself)
-//         cx.set_shared_state("ˇthe quick brown fox").await;
-//         cx.simulate_shared_keystrokes(["2", "~", "."]).await;
-//         deterministic.run_until_parked();
-//         cx.set_shared_state("THE ˇquick brown fox").await;
-//         cx.simulate_shared_keystrokes(["3", "."]).await;
-//         deterministic.run_until_parked();
-//         cx.set_shared_state("THE QUIˇck brown fox").await;
-//         deterministic.run_until_parked();
-//         cx.simulate_shared_keystrokes(["."]).await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state("THE QUICK ˇbrown fox").await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_repeat_ime(deterministic: Arc<Deterministic>, cx: &mut gpui::TestAppContext) {
-//         let mut cx = VimTestContext::new(cx, true).await;
-
-//         cx.set_state("hˇllo", Mode::Normal);
-//         cx.simulate_keystrokes(["i"]);
-
-//         // simulate brazilian input for ä.
-//         cx.update_editor(|editor, cx| {
-//             editor.replace_and_mark_text_in_range(None, "\"", Some(1..1), cx);
-//             editor.replace_text_in_range(None, "ä", cx);
-//         });
-//         cx.simulate_keystrokes(["escape"]);
-//         cx.assert_state("hˇällo", Mode::Normal);
-//         cx.simulate_keystrokes(["."]);
-//         deterministic.run_until_parked();
-//         cx.assert_state("hˇäällo", Mode::Normal);
-//     }
-
-//     #[gpui::test]
-//     async fn test_repeat_completion(
-//         deterministic: Arc<Deterministic>,
-//         cx: &mut gpui::TestAppContext,
-//     ) {
-//         let cx = EditorLspTestContext::new_rust(
-//             lsp::ServerCapabilities {
-//                 completion_provider: Some(lsp::CompletionOptions {
-//                     trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
-//                     resolve_provider: Some(true),
-//                     ..Default::default()
-//                 }),
-//                 ..Default::default()
-//             },
-//             cx,
-//         )
-//         .await;
-//         let mut cx = VimTestContext::new_with_lsp(cx, true);
-
-//         cx.set_state(
-//             indoc! {"
-//             onˇe
-//             two
-//             three
-//         "},
-//             Mode::Normal,
-//         );
-
-//         let mut request =
-//             cx.handle_request::<lsp::request::Completion, _, _>(move |_, params, _| async move {
-//                 let position = params.text_document_position.position;
-//                 Ok(Some(lsp::CompletionResponse::Array(vec![
-//                     lsp::CompletionItem {
-//                         label: "first".to_string(),
-//                         text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
-//                             range: lsp::Range::new(position.clone(), position.clone()),
-//                             new_text: "first".to_string(),
-//                         })),
-//                         ..Default::default()
-//                     },
-//                     lsp::CompletionItem {
-//                         label: "second".to_string(),
-//                         text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
-//                             range: lsp::Range::new(position.clone(), position.clone()),
-//                             new_text: "second".to_string(),
-//                         })),
-//                         ..Default::default()
-//                     },
-//                 ])))
-//             });
-//         cx.simulate_keystrokes(["a", "."]);
-//         request.next().await;
-//         cx.condition(|editor, _| editor.context_menu_visible())
-//             .await;
-//         cx.simulate_keystrokes(["down", "enter", "!", "escape"]);
-
-//         cx.assert_state(
-//             indoc! {"
-//                 one.secondˇ!
-//                 two
-//                 three
-//             "},
-//             Mode::Normal,
-//         );
-//         cx.simulate_keystrokes(["j", "."]);
-//         deterministic.run_until_parked();
-//         cx.assert_state(
-//             indoc! {"
-//                 one.second!
-//                 two.secondˇ!
-//                 three
-//             "},
-//             Mode::Normal,
-//         );
-//     }
-
-//     #[gpui::test]
-//     async fn test_repeat_visual(deterministic: Arc<Deterministic>, cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         // single-line (3 columns)
-//         cx.set_shared_state(indoc! {
-//             "ˇthe quick brown
-//             fox jumps over
-//             the lazy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["v", "i", "w", "s", "o", "escape"])
-//             .await;
-//         cx.assert_shared_state(indoc! {
-//             "ˇo quick brown
-//             fox jumps over
-//             the lazy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["j", "w", "."]).await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state(indoc! {
-//             "o quick brown
-//             fox ˇops over
-//             the lazy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["f", "r", "."]).await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state(indoc! {
-//             "o quick brown
-//             fox ops oveˇothe lazy dog"
-//         })
-//         .await;
-
-//         // visual
-//         cx.set_shared_state(indoc! {
-//             "the ˇquick brown
-//             fox jumps over
-//             fox jumps over
-//             fox jumps over
-//             the lazy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["v", "j", "x"]).await;
-//         cx.assert_shared_state(indoc! {
-//             "the ˇumps over
-//             fox jumps over
-//             fox jumps over
-//             the lazy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["."]).await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state(indoc! {
-//             "the ˇumps over
-//             fox jumps over
-//             the lazy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["w", "."]).await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state(indoc! {
-//             "the umps ˇumps over
-//             the lazy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["j", "."]).await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state(indoc! {
-//             "the umps umps over
-//             the ˇog"
-//         })
-//         .await;
-
-//         // block mode (3 rows)
-//         cx.set_shared_state(indoc! {
-//             "ˇthe quick brown
-//             fox jumps over
-//             the lazy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["ctrl-v", "j", "j", "shift-i", "o", "escape"])
-//             .await;
-//         cx.assert_shared_state(indoc! {
-//             "ˇothe quick brown
-//             ofox jumps over
-//             othe lazy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["j", "4", "l", "."]).await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state(indoc! {
-//             "othe quick brown
-//             ofoxˇo jumps over
-//             otheo lazy dog"
-//         })
-//         .await;
-
-//         // line mode
-//         cx.set_shared_state(indoc! {
-//             "ˇthe quick brown
-//             fox jumps over
-//             the lazy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["shift-v", "shift-r", "o", "escape"])
-//             .await;
-//         cx.assert_shared_state(indoc! {
-//             "ˇo
-//             fox jumps over
-//             the lazy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["j", "."]).await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state(indoc! {
-//             "o
-//             ˇo
-//             the lazy dog"
-//         })
-//         .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_repeat_motion_counts(
-//         deterministic: Arc<Deterministic>,
-//         cx: &mut gpui::TestAppContext,
-//     ) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.set_shared_state(indoc! {
-//             "ˇthe quick brown
-//             fox jumps over
-//             the lazy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["3", "d", "3", "l"]).await;
-//         cx.assert_shared_state(indoc! {
-//             "ˇ brown
-//             fox jumps over
-//             the lazy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["j", "."]).await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state(indoc! {
-//             " brown
-//             ˇ over
-//             the lazy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["j", "2", "."]).await;
-//         deterministic.run_until_parked();
-//         cx.assert_shared_state(indoc! {
-//             " brown
-//              over
-//             ˇe lazy dog"
-//         })
-//         .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_record_interrupted(
-//         deterministic: Arc<Deterministic>,
-//         cx: &mut gpui::TestAppContext,
-//     ) {
-//         let mut cx = VimTestContext::new(cx, true).await;
-
-//         cx.set_state("ˇhello\n", Mode::Normal);
-//         cx.simulate_keystrokes(["4", "i", "j", "cmd-shift-p", "escape", "escape"]);
-//         deterministic.run_until_parked();
-//         cx.assert_state("ˇjhello\n", Mode::Normal);
-//     }
-// }
+#[cfg(test)]
+mod test {
+    use editor::test::editor_lsp_test_context::EditorLspTestContext;
+    use futures::StreamExt;
+    use indoc::indoc;
+
+    use gpui::InputHandler;
+
+    use crate::{
+        state::Mode,
+        test::{NeovimBackedTestContext, VimTestContext},
+    };
+
+    #[gpui::test]
+    async fn test_dot_repeat(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        // "o"
+        cx.set_shared_state("ˇhello").await;
+        cx.simulate_shared_keystrokes(["o", "w", "o", "r", "l", "d", "escape"])
+            .await;
+        cx.assert_shared_state("hello\nworlˇd").await;
+        cx.simulate_shared_keystrokes(["."]).await;
+        cx.assert_shared_state("hello\nworld\nworlˇd").await;
+
+        // "d"
+        cx.simulate_shared_keystrokes(["^", "d", "f", "o"]).await;
+        cx.simulate_shared_keystrokes(["g", "g", "."]).await;
+        cx.assert_shared_state("ˇ\nworld\nrld").await;
+
+        // "p" (note that it pastes the current clipboard)
+        cx.simulate_shared_keystrokes(["j", "y", "y", "p"]).await;
+        cx.simulate_shared_keystrokes(["shift-g", "y", "y", "."])
+            .await;
+        cx.assert_shared_state("\nworld\nworld\nrld\nˇrld").await;
+
+        // "~" (note that counts apply to the action taken, not . itself)
+        cx.set_shared_state("ˇthe quick brown fox").await;
+        cx.simulate_shared_keystrokes(["2", "~", "."]).await;
+        cx.set_shared_state("THE ˇquick brown fox").await;
+        cx.simulate_shared_keystrokes(["3", "."]).await;
+        cx.set_shared_state("THE QUIˇck brown fox").await;
+        cx.run_until_parked();
+        cx.simulate_shared_keystrokes(["."]).await;
+        cx.assert_shared_state("THE QUICK ˇbrown fox").await;
+    }
+
+    #[gpui::test]
+    async fn test_repeat_ime(cx: &mut gpui::TestAppContext) {
+        let mut cx = VimTestContext::new(cx, true).await;
+
+        cx.set_state("hˇllo", Mode::Normal);
+        cx.simulate_keystrokes(["i"]);
+
+        // simulate brazilian input for ä.
+        cx.update_editor(|editor, cx| {
+            editor.replace_and_mark_text_in_range(None, "\"", Some(1..1), cx);
+            editor.replace_text_in_range(None, "ä", cx);
+        });
+        cx.simulate_keystrokes(["escape"]);
+        cx.assert_state("hˇällo", Mode::Normal);
+        cx.simulate_keystrokes(["."]);
+        cx.assert_state("hˇäällo", Mode::Normal);
+    }
+
+    #[gpui::test]
+    async fn test_repeat_completion(cx: &mut gpui::TestAppContext) {
+        VimTestContext::init(cx);
+        let cx = EditorLspTestContext::new_rust(
+            lsp::ServerCapabilities {
+                completion_provider: Some(lsp::CompletionOptions {
+                    trigger_characters: Some(vec![".".to_string(), ":".to_string()]),
+                    resolve_provider: Some(true),
+                    ..Default::default()
+                }),
+                ..Default::default()
+            },
+            cx,
+        )
+        .await;
+        let mut cx = VimTestContext::new_with_lsp(cx, true);
+
+        cx.set_state(
+            indoc! {"
+            onˇe
+            two
+            three
+        "},
+            Mode::Normal,
+        );
+
+        let mut request =
+            cx.handle_request::<lsp::request::Completion, _, _>(move |_, params, _| async move {
+                let position = params.text_document_position.position;
+                Ok(Some(lsp::CompletionResponse::Array(vec![
+                    lsp::CompletionItem {
+                        label: "first".to_string(),
+                        text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
+                            range: lsp::Range::new(position.clone(), position.clone()),
+                            new_text: "first".to_string(),
+                        })),
+                        ..Default::default()
+                    },
+                    lsp::CompletionItem {
+                        label: "second".to_string(),
+                        text_edit: Some(lsp::CompletionTextEdit::Edit(lsp::TextEdit {
+                            range: lsp::Range::new(position.clone(), position.clone()),
+                            new_text: "second".to_string(),
+                        })),
+                        ..Default::default()
+                    },
+                ])))
+            });
+        cx.simulate_keystrokes(["a", "."]);
+        request.next().await;
+        cx.condition(|editor, _| editor.context_menu_visible())
+            .await;
+        cx.simulate_keystrokes(["down", "enter", "!", "escape"]);
+
+        cx.assert_state(
+            indoc! {"
+                one.secondˇ!
+                two
+                three
+            "},
+            Mode::Normal,
+        );
+        cx.simulate_keystrokes(["j", "."]);
+        cx.assert_state(
+            indoc! {"
+                one.second!
+                two.secondˇ!
+                three
+            "},
+            Mode::Normal,
+        );
+    }
+
+    #[gpui::test]
+    async fn test_repeat_visual(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        // single-line (3 columns)
+        cx.set_shared_state(indoc! {
+            "ˇthe quick brown
+            fox jumps over
+            the lazy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["v", "i", "w", "s", "o", "escape"])
+            .await;
+        cx.assert_shared_state(indoc! {
+            "ˇo quick brown
+            fox jumps over
+            the lazy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["j", "w", "."]).await;
+        cx.assert_shared_state(indoc! {
+            "o quick brown
+            fox ˇops over
+            the lazy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["f", "r", "."]).await;
+        cx.assert_shared_state(indoc! {
+            "o quick brown
+            fox ops oveˇothe lazy dog"
+        })
+        .await;
+
+        // visual
+        cx.set_shared_state(indoc! {
+            "the ˇquick brown
+            fox jumps over
+            fox jumps over
+            fox jumps over
+            the lazy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["v", "j", "x"]).await;
+        cx.assert_shared_state(indoc! {
+            "the ˇumps over
+            fox jumps over
+            fox jumps over
+            the lazy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["."]).await;
+        cx.assert_shared_state(indoc! {
+            "the ˇumps over
+            fox jumps over
+            the lazy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["w", "."]).await;
+        cx.assert_shared_state(indoc! {
+            "the umps ˇumps over
+            the lazy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["j", "."]).await;
+        cx.assert_shared_state(indoc! {
+            "the umps umps over
+            the ˇog"
+        })
+        .await;
+
+        // block mode (3 rows)
+        cx.set_shared_state(indoc! {
+            "ˇthe quick brown
+            fox jumps over
+            the lazy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["ctrl-v", "j", "j", "shift-i", "o", "escape"])
+            .await;
+        cx.assert_shared_state(indoc! {
+            "ˇothe quick brown
+            ofox jumps over
+            othe lazy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["j", "4", "l", "."]).await;
+        cx.assert_shared_state(indoc! {
+            "othe quick brown
+            ofoxˇo jumps over
+            otheo lazy dog"
+        })
+        .await;
+
+        // line mode
+        cx.set_shared_state(indoc! {
+            "ˇthe quick brown
+            fox jumps over
+            the lazy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["shift-v", "shift-r", "o", "escape"])
+            .await;
+        cx.assert_shared_state(indoc! {
+            "ˇo
+            fox jumps over
+            the lazy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["j", "."]).await;
+        cx.assert_shared_state(indoc! {
+            "o
+            ˇo
+            the lazy dog"
+        })
+        .await;
+    }
+
+    #[gpui::test]
+    async fn test_repeat_motion_counts(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.set_shared_state(indoc! {
+            "ˇthe quick brown
+            fox jumps over
+            the lazy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["3", "d", "3", "l"]).await;
+        cx.assert_shared_state(indoc! {
+            "ˇ brown
+            fox jumps over
+            the lazy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["j", "."]).await;
+        cx.assert_shared_state(indoc! {
+            " brown
+            ˇ over
+            the lazy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["j", "2", "."]).await;
+        cx.assert_shared_state(indoc! {
+            " brown
+             over
+            ˇe lazy dog"
+        })
+        .await;
+    }
+
+    #[gpui::test]
+    async fn test_record_interrupted(cx: &mut gpui::TestAppContext) {
+        let mut cx = VimTestContext::new(cx, true).await;
+
+        cx.set_state("ˇhello\n", Mode::Normal);
+        cx.simulate_keystrokes(["4", "i", "j", "cmd-shift-p", "escape"]);
+        cx.simulate_keystrokes(["escape"]);
+        cx.assert_state("ˇjhello\n", Mode::Normal);
+    }
+}

crates/vim2/src/normal/scroll.rs 🔗

@@ -108,122 +108,140 @@ fn scroll_editor(
     }
 }
 
-// #[cfg(test)]
-// mod test {
-//     use crate::{
-//         state::Mode,
-//         test::{NeovimBackedTestContext, VimTestContext},
-//     };
-//     use gpui::geometry::vector::vec2f;
-//     use indoc::indoc;
-//     use language::Point;
-
-//     #[gpui::test]
-//     async fn test_scroll(cx: &mut gpui::TestAppContext) {
-//         let mut cx = VimTestContext::new(cx, true).await;
-
-//         let window = cx.window;
-//         let line_height = cx.editor(|editor, cx| editor.style().text.line_height(cx.font_cache()));
-//         window.simulate_resize(vec2f(1000., 8.0 * line_height - 1.0), &mut cx);
-
-//         cx.set_state(
-//             indoc!(
-//                 "ˇone
-//                 two
-//                 three
-//                 four
-//                 five
-//                 six
-//                 seven
-//                 eight
-//                 nine
-//                 ten
-//                 eleven
-//                 twelve
-//             "
-//             ),
-//             Mode::Normal,
-//         );
-
-//         cx.update_editor(|editor, cx| {
-//             assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 0.))
-//         });
-//         cx.simulate_keystrokes(["ctrl-e"]);
-//         cx.update_editor(|editor, cx| {
-//             assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 1.))
-//         });
-//         cx.simulate_keystrokes(["2", "ctrl-e"]);
-//         cx.update_editor(|editor, cx| {
-//             assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 3.))
-//         });
-//         cx.simulate_keystrokes(["ctrl-y"]);
-//         cx.update_editor(|editor, cx| {
-//             assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 2.))
-//         });
-
-//         // does not select in normal mode
-//         cx.simulate_keystrokes(["g", "g"]);
-//         cx.update_editor(|editor, cx| {
-//             assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 0.))
-//         });
-//         cx.simulate_keystrokes(["ctrl-d"]);
-//         cx.update_editor(|editor, cx| {
-//             assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 3.0));
-//             assert_eq!(
-//                 editor.selections.newest(cx).range(),
-//                 Point::new(6, 0)..Point::new(6, 0)
-//             )
-//         });
-
-//         // does select in visual mode
-//         cx.simulate_keystrokes(["g", "g"]);
-//         cx.update_editor(|editor, cx| {
-//             assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 0.))
-//         });
-//         cx.simulate_keystrokes(["v", "ctrl-d"]);
-//         cx.update_editor(|editor, cx| {
-//             assert_eq!(editor.snapshot(cx).scroll_position(), vec2f(0., 3.0));
-//             assert_eq!(
-//                 editor.selections.newest(cx).range(),
-//                 Point::new(0, 0)..Point::new(6, 1)
-//             )
-//         });
-//     }
-//     #[gpui::test]
-//     async fn test_ctrl_d_u(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.set_scroll_height(10).await;
-
-//         pub fn sample_text(rows: usize, cols: usize, start_char: char) -> String {
-//             let mut text = String::new();
-//             for row in 0..rows {
-//                 let c: char = (start_char as u32 + row as u32) as u8 as char;
-//                 let mut line = c.to_string().repeat(cols);
-//                 if row < rows - 1 {
-//                     line.push('\n');
-//                 }
-//                 text += &line;
-//             }
-//             text
-//         }
-//         let content = "ˇ".to_owned() + &sample_text(26, 2, 'a');
-//         cx.set_shared_state(&content).await;
-
-//         // skip over the scrolloff at the top
-//         // test ctrl-d
-//         cx.simulate_shared_keystrokes(["4", "j", "ctrl-d"]).await;
-//         cx.assert_state_matches().await;
-//         cx.simulate_shared_keystrokes(["ctrl-d"]).await;
-//         cx.assert_state_matches().await;
-//         cx.simulate_shared_keystrokes(["g", "g", "ctrl-d"]).await;
-//         cx.assert_state_matches().await;
-
-//         // test ctrl-u
-//         cx.simulate_shared_keystrokes(["ctrl-u"]).await;
-//         cx.assert_state_matches().await;
-//         cx.simulate_shared_keystrokes(["ctrl-d", "ctrl-d", "4", "j", "ctrl-u", "ctrl-u"])
-//             .await;
-//         cx.assert_state_matches().await;
-//     }
-// }
+#[cfg(test)]
+mod test {
+    use crate::{
+        state::Mode,
+        test::{NeovimBackedTestContext, VimTestContext},
+    };
+    use gpui::{point, px, size, Context};
+    use indoc::indoc;
+    use language::Point;
+
+    #[gpui::test]
+    async fn test_scroll(cx: &mut gpui::TestAppContext) {
+        let mut cx = VimTestContext::new(cx, true).await;
+
+        let (line_height, visible_line_count) = cx.editor(|editor, cx| {
+            (
+                editor
+                    .style()
+                    .unwrap()
+                    .text
+                    .line_height_in_pixels(cx.rem_size()),
+                editor.visible_line_count().unwrap(),
+            )
+        });
+
+        let window = cx.window;
+        let margin = cx
+            .update_window(window, |_, cx| {
+                cx.viewport_size().height - line_height * visible_line_count
+            })
+            .unwrap();
+        cx.simulate_window_resize(
+            cx.window,
+            size(px(1000.), margin + 8. * line_height - px(1.0)),
+        );
+
+        cx.set_state(
+            indoc!(
+                "ˇone
+                two
+                three
+                four
+                five
+                six
+                seven
+                eight
+                nine
+                ten
+                eleven
+                twelve
+            "
+            ),
+            Mode::Normal,
+        );
+
+        cx.update_editor(|editor, cx| {
+            assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 0.))
+        });
+        cx.simulate_keystrokes(["ctrl-e"]);
+        cx.update_editor(|editor, cx| {
+            assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 1.))
+        });
+        cx.simulate_keystrokes(["2", "ctrl-e"]);
+        cx.update_editor(|editor, cx| {
+            assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 3.))
+        });
+        cx.simulate_keystrokes(["ctrl-y"]);
+        cx.update_editor(|editor, cx| {
+            assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 2.))
+        });
+
+        // does not select in normal mode
+        cx.simulate_keystrokes(["g", "g"]);
+        cx.update_editor(|editor, cx| {
+            assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 0.))
+        });
+        cx.simulate_keystrokes(["ctrl-d"]);
+        cx.update_editor(|editor, cx| {
+            assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 3.0));
+            assert_eq!(
+                editor.selections.newest(cx).range(),
+                Point::new(6, 0)..Point::new(6, 0)
+            )
+        });
+
+        // does select in visual mode
+        cx.simulate_keystrokes(["g", "g"]);
+        cx.update_editor(|editor, cx| {
+            assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 0.))
+        });
+        cx.simulate_keystrokes(["v", "ctrl-d"]);
+        cx.update_editor(|editor, cx| {
+            assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 3.0));
+            assert_eq!(
+                editor.selections.newest(cx).range(),
+                Point::new(0, 0)..Point::new(6, 1)
+            )
+        });
+    }
+    #[gpui::test]
+    async fn test_ctrl_d_u(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.set_scroll_height(10).await;
+
+        pub fn sample_text(rows: usize, cols: usize, start_char: char) -> String {
+            let mut text = String::new();
+            for row in 0..rows {
+                let c: char = (start_char as u32 + row as u32) as u8 as char;
+                let mut line = c.to_string().repeat(cols);
+                if row < rows - 1 {
+                    line.push('\n');
+                }
+                text += &line;
+            }
+            text
+        }
+        let content = "ˇ".to_owned() + &sample_text(26, 2, 'a');
+        cx.set_shared_state(&content).await;
+
+        // skip over the scrolloff at the top
+        // test ctrl-d
+        cx.simulate_shared_keystrokes(["4", "j", "ctrl-d"]).await;
+        cx.assert_state_matches().await;
+        cx.simulate_shared_keystrokes(["ctrl-d"]).await;
+        cx.assert_state_matches().await;
+        cx.simulate_shared_keystrokes(["g", "g", "ctrl-d"]).await;
+        cx.assert_state_matches().await;
+
+        // test ctrl-u
+        cx.simulate_shared_keystrokes(["ctrl-u"]).await;
+        cx.assert_state_matches().await;
+        cx.simulate_shared_keystrokes(["ctrl-d", "ctrl-d", "4", "j", "ctrl-u", "ctrl-u"])
+            .await;
+        cx.assert_state_matches().await;
+    }
+}

crates/vim2/src/normal/search.rs 🔗

@@ -347,58 +347,50 @@ fn parse_replace_all(query: &str) -> Replacement {
 
 // #[cfg(test)]
 // mod test {
-//     use std::sync::Arc;
-
 //     use editor::DisplayPoint;
 //     use search::BufferSearchBar;
 
 //     use crate::{state::Mode, test::VimTestContext};
 
 //     #[gpui::test]
-//     async fn test_move_to_next(
-//         cx: &mut gpui::TestAppContext,
-//         deterministic: Arc<gpui::executor::Deterministic>,
-//     ) {
+//     async fn test_move_to_next(cx: &mut gpui::TestAppContext) {
 //         let mut cx = VimTestContext::new(cx, true).await;
 //         cx.set_state("ˇhi\nhigh\nhi\n", Mode::Normal);
 
 //         cx.simulate_keystrokes(["*"]);
-//         deterministic.run_until_parked();
+//         cx.run_until_parked();
 //         cx.assert_state("hi\nhigh\nˇhi\n", Mode::Normal);
 
 //         cx.simulate_keystrokes(["*"]);
-//         deterministic.run_until_parked();
+//         cx.run_until_parked();
 //         cx.assert_state("ˇhi\nhigh\nhi\n", Mode::Normal);
 
 //         cx.simulate_keystrokes(["#"]);
-//         deterministic.run_until_parked();
+//         cx.run_until_parked();
 //         cx.assert_state("hi\nhigh\nˇhi\n", Mode::Normal);
 
 //         cx.simulate_keystrokes(["#"]);
-//         deterministic.run_until_parked();
+//         cx.run_until_parked();
 //         cx.assert_state("ˇhi\nhigh\nhi\n", Mode::Normal);
 
 //         cx.simulate_keystrokes(["2", "*"]);
-//         deterministic.run_until_parked();
+//         cx.run_until_parked();
 //         cx.assert_state("ˇhi\nhigh\nhi\n", Mode::Normal);
 
 //         cx.simulate_keystrokes(["g", "*"]);
-//         deterministic.run_until_parked();
+//         cx.run_until_parked();
 //         cx.assert_state("hi\nˇhigh\nhi\n", Mode::Normal);
 
 //         cx.simulate_keystrokes(["n"]);
 //         cx.assert_state("hi\nhigh\nˇhi\n", Mode::Normal);
 
 //         cx.simulate_keystrokes(["g", "#"]);
-//         deterministic.run_until_parked();
+//         cx.run_until_parked();
 //         cx.assert_state("hi\nˇhigh\nhi\n", Mode::Normal);
 //     }
 
 //     #[gpui::test]
-//     async fn test_search(
-//         cx: &mut gpui::TestAppContext,
-//         deterministic: Arc<gpui::executor::Deterministic>,
-//     ) {
+//     async fn test_search(cx: &mut gpui::TestAppContext) {
 //         let mut cx = VimTestContext::new(cx, true).await;
 
 //         cx.set_state("aa\nbˇb\ncc\ncc\ncc\n", Mode::Normal);
@@ -414,11 +406,11 @@ fn parse_replace_all(query: &str) -> Replacement {
 //                 .expect("Buffer search bar should be deployed")
 //         });
 
-//         search_bar.read_with(cx.cx, |bar, cx| {
+//         cx.update_view(search_bar, |bar, cx| {
 //             assert_eq!(bar.query(cx), "cc");
 //         });
 
-//         deterministic.run_until_parked();
+//         cx.run_until_parked();
 
 //         cx.update_editor(|editor, cx| {
 //             let highlights = editor.all_text_background_highlights(cx);
@@ -440,51 +432,41 @@ fn parse_replace_all(query: &str) -> Replacement {
 
 //         // ?<enter> to go to previous
 //         cx.simulate_keystrokes(["?", "enter"]);
-//         deterministic.run_until_parked();
 //         cx.assert_state("aa\nbb\ncc\ncc\nˇcc\n", Mode::Normal);
 //         cx.simulate_keystrokes(["?", "enter"]);
-//         deterministic.run_until_parked();
 //         cx.assert_state("aa\nbb\ncc\nˇcc\ncc\n", Mode::Normal);
 
 //         // /<enter> to go to next
 //         cx.simulate_keystrokes(["/", "enter"]);
-//         deterministic.run_until_parked();
 //         cx.assert_state("aa\nbb\ncc\ncc\nˇcc\n", Mode::Normal);
 
 //         // ?{search}<enter> to search backwards
 //         cx.simulate_keystrokes(["?", "b", "enter"]);
-//         deterministic.run_until_parked();
 //         cx.assert_state("aa\nbˇb\ncc\ncc\ncc\n", Mode::Normal);
 
 //         // works with counts
 //         cx.simulate_keystrokes(["4", "/", "c"]);
-//         deterministic.run_until_parked();
 //         cx.simulate_keystrokes(["enter"]);
 //         cx.assert_state("aa\nbb\ncc\ncˇc\ncc\n", Mode::Normal);
 
 //         // check that searching resumes from cursor, not previous match
 //         cx.set_state("ˇaa\nbb\ndd\ncc\nbb\n", Mode::Normal);
 //         cx.simulate_keystrokes(["/", "d"]);
-//         deterministic.run_until_parked();
 //         cx.simulate_keystrokes(["enter"]);
 //         cx.assert_state("aa\nbb\nˇdd\ncc\nbb\n", Mode::Normal);
 //         cx.update_editor(|editor, cx| editor.move_to_beginning(&Default::default(), cx));
 //         cx.assert_state("ˇaa\nbb\ndd\ncc\nbb\n", Mode::Normal);
 //         cx.simulate_keystrokes(["/", "b"]);
-//         deterministic.run_until_parked();
 //         cx.simulate_keystrokes(["enter"]);
 //         cx.assert_state("aa\nˇbb\ndd\ncc\nbb\n", Mode::Normal);
 //     }
 
 //     #[gpui::test]
-//     async fn test_non_vim_search(
-//         cx: &mut gpui::TestAppContext,
-//         deterministic: Arc<gpui::executor::Deterministic>,
-//     ) {
+//     async fn test_non_vim_search(cx: &mut gpui::TestAppContext) {
 //         let mut cx = VimTestContext::new(cx, false).await;
 //         cx.set_state("ˇone one one one", Mode::Normal);
 //         cx.simulate_keystrokes(["cmd-f"]);
-//         deterministic.run_until_parked();
+//         cx.run_until_parked();
 
 //         cx.assert_editor_state("«oneˇ» one one one");
 //         cx.simulate_keystrokes(["enter"]);

crates/vim2/src/normal/substitute.rs 🔗

@@ -81,196 +81,196 @@ pub fn substitute(vim: &mut Vim, count: Option<usize>, line_mode: bool, cx: &mut
     vim.switch_mode(Mode::Insert, true, cx);
 }
 
-// #[cfg(test)]
-// mod test {
-//     use crate::{
-//         state::Mode,
-//         test::{NeovimBackedTestContext, VimTestContext},
-//     };
-//     use indoc::indoc;
+#[cfg(test)]
+mod test {
+    use crate::{
+        state::Mode,
+        test::{NeovimBackedTestContext, VimTestContext},
+    };
+    use indoc::indoc;
 
-//     #[gpui::test]
-//     async fn test_substitute(cx: &mut gpui::TestAppContext) {
-//         let mut cx = VimTestContext::new(cx, true).await;
+    #[gpui::test]
+    async fn test_substitute(cx: &mut gpui::TestAppContext) {
+        let mut cx = VimTestContext::new(cx, true).await;
 
-//         // supports a single cursor
-//         cx.set_state(indoc! {"ˇabc\n"}, Mode::Normal);
-//         cx.simulate_keystrokes(["s", "x"]);
-//         cx.assert_editor_state("xˇbc\n");
+        // supports a single cursor
+        cx.set_state(indoc! {"ˇabc\n"}, Mode::Normal);
+        cx.simulate_keystrokes(["s", "x"]);
+        cx.assert_editor_state("xˇbc\n");
 
-//         // supports a selection
-//         cx.set_state(indoc! {"a«bcˇ»\n"}, Mode::Visual);
-//         cx.assert_editor_state("a«bcˇ»\n");
-//         cx.simulate_keystrokes(["s", "x"]);
-//         cx.assert_editor_state("axˇ\n");
+        // supports a selection
+        cx.set_state(indoc! {"a«bcˇ»\n"}, Mode::Visual);
+        cx.assert_editor_state("a«bcˇ»\n");
+        cx.simulate_keystrokes(["s", "x"]);
+        cx.assert_editor_state("axˇ\n");
 
-//         // supports counts
-//         cx.set_state(indoc! {"ˇabc\n"}, Mode::Normal);
-//         cx.simulate_keystrokes(["2", "s", "x"]);
-//         cx.assert_editor_state("xˇc\n");
+        // supports counts
+        cx.set_state(indoc! {"ˇabc\n"}, Mode::Normal);
+        cx.simulate_keystrokes(["2", "s", "x"]);
+        cx.assert_editor_state("xˇc\n");
 
-//         // supports multiple cursors
-//         cx.set_state(indoc! {"a«bcˇ»deˇffg\n"}, Mode::Normal);
-//         cx.simulate_keystrokes(["2", "s", "x"]);
-//         cx.assert_editor_state("axˇdexˇg\n");
+        // supports multiple cursors
+        cx.set_state(indoc! {"a«bcˇ»deˇffg\n"}, Mode::Normal);
+        cx.simulate_keystrokes(["2", "s", "x"]);
+        cx.assert_editor_state("axˇdexˇg\n");
 
-//         // does not read beyond end of line
-//         cx.set_state(indoc! {"ˇabc\n"}, Mode::Normal);
-//         cx.simulate_keystrokes(["5", "s", "x"]);
-//         cx.assert_editor_state("xˇ\n");
+        // does not read beyond end of line
+        cx.set_state(indoc! {"ˇabc\n"}, Mode::Normal);
+        cx.simulate_keystrokes(["5", "s", "x"]);
+        cx.assert_editor_state("xˇ\n");
 
-//         // it handles multibyte characters
-//         cx.set_state(indoc! {"ˇcàfé\n"}, Mode::Normal);
-//         cx.simulate_keystrokes(["4", "s"]);
-//         cx.assert_editor_state("ˇ\n");
+        // it handles multibyte characters
+        cx.set_state(indoc! {"ˇcàfé\n"}, Mode::Normal);
+        cx.simulate_keystrokes(["4", "s"]);
+        cx.assert_editor_state("ˇ\n");
 
-//         // should transactionally undo selection changes
-//         cx.simulate_keystrokes(["escape", "u"]);
-//         cx.assert_editor_state("ˇcàfé\n");
+        // should transactionally undo selection changes
+        cx.simulate_keystrokes(["escape", "u"]);
+        cx.assert_editor_state("ˇcàfé\n");
 
-//         // it handles visual line mode
-//         cx.set_state(
-//             indoc! {"
-//             alpha
-//               beˇta
-//             gamma"},
-//             Mode::Normal,
-//         );
-//         cx.simulate_keystrokes(["shift-v", "s"]);
-//         cx.assert_editor_state(indoc! {"
-//             alpha
-//               ˇ
-//             gamma"});
-//     }
+        // it handles visual line mode
+        cx.set_state(
+            indoc! {"
+            alpha
+              beˇta
+            gamma"},
+            Mode::Normal,
+        );
+        cx.simulate_keystrokes(["shift-v", "s"]);
+        cx.assert_editor_state(indoc! {"
+            alpha
+              ˇ
+            gamma"});
+    }
 
-//     #[gpui::test]
-//     async fn test_visual_change(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
+    #[gpui::test]
+    async fn test_visual_change(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
 
-//         cx.set_shared_state("The quick ˇbrown").await;
-//         cx.simulate_shared_keystrokes(["v", "w", "c"]).await;
-//         cx.assert_shared_state("The quick ˇ").await;
+        cx.set_shared_state("The quick ˇbrown").await;
+        cx.simulate_shared_keystrokes(["v", "w", "c"]).await;
+        cx.assert_shared_state("The quick ˇ").await;
 
-//         cx.set_shared_state(indoc! {"
-//             The ˇquick brown
-//             fox jumps over
-//             the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["v", "w", "j", "c"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             The ˇver
-//             the lazy dog"})
-//             .await;
+        cx.set_shared_state(indoc! {"
+            The ˇquick brown
+            fox jumps over
+            the lazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["v", "w", "j", "c"]).await;
+        cx.assert_shared_state(indoc! {"
+            The ˇver
+            the lazy dog"})
+            .await;
 
-//         let cases = cx.each_marked_position(indoc! {"
-//             The ˇquick brown
-//             fox jumps ˇover
-//             the ˇlazy dog"});
-//         for initial_state in cases {
-//             cx.assert_neovim_compatible(&initial_state, ["v", "w", "j", "c"])
-//                 .await;
-//             cx.assert_neovim_compatible(&initial_state, ["v", "w", "k", "c"])
-//                 .await;
-//         }
-//     }
+        let cases = cx.each_marked_position(indoc! {"
+            The ˇquick brown
+            fox jumps ˇover
+            the ˇlazy dog"});
+        for initial_state in cases {
+            cx.assert_neovim_compatible(&initial_state, ["v", "w", "j", "c"])
+                .await;
+            cx.assert_neovim_compatible(&initial_state, ["v", "w", "k", "c"])
+                .await;
+        }
+    }
 
-//     #[gpui::test]
-//     async fn test_visual_line_change(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx)
-//             .await
-//             .binding(["shift-v", "c"]);
-//         cx.assert(indoc! {"
-//             The quˇick brown
-//             fox jumps over
-//             the lazy dog"})
-//             .await;
-//         // Test pasting code copied on change
-//         cx.simulate_shared_keystrokes(["escape", "j", "p"]).await;
-//         cx.assert_state_matches().await;
+    #[gpui::test]
+    async fn test_visual_line_change(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx)
+            .await
+            .binding(["shift-v", "c"]);
+        cx.assert(indoc! {"
+            The quˇick brown
+            fox jumps over
+            the lazy dog"})
+            .await;
+        // Test pasting code copied on change
+        cx.simulate_shared_keystrokes(["escape", "j", "p"]).await;
+        cx.assert_state_matches().await;
 
-//         cx.assert_all(indoc! {"
-//             The quick brown
-//             fox juˇmps over
-//             the laˇzy dog"})
-//             .await;
-//         let mut cx = cx.binding(["shift-v", "j", "c"]);
-//         cx.assert(indoc! {"
-//             The quˇick brown
-//             fox jumps over
-//             the lazy dog"})
-//             .await;
-//         // Test pasting code copied on delete
-//         cx.simulate_shared_keystrokes(["escape", "j", "p"]).await;
-//         cx.assert_state_matches().await;
+        cx.assert_all(indoc! {"
+            The quick brown
+            fox juˇmps over
+            the laˇzy dog"})
+            .await;
+        let mut cx = cx.binding(["shift-v", "j", "c"]);
+        cx.assert(indoc! {"
+            The quˇick brown
+            fox jumps over
+            the lazy dog"})
+            .await;
+        // Test pasting code copied on delete
+        cx.simulate_shared_keystrokes(["escape", "j", "p"]).await;
+        cx.assert_state_matches().await;
 
-//         cx.assert_all(indoc! {"
-//             The quick brown
-//             fox juˇmps over
-//             the laˇzy dog"})
-//             .await;
-//     }
+        cx.assert_all(indoc! {"
+            The quick brown
+            fox juˇmps over
+            the laˇzy dog"})
+            .await;
+    }
 
-//     #[gpui::test]
-//     async fn test_substitute_line(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
+    #[gpui::test]
+    async fn test_substitute_line(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
 
-//         let initial_state = indoc! {"
-//                     The quick brown
-//                     fox juˇmps over
-//                     the lazy dog
-//                     "};
+        let initial_state = indoc! {"
+                    The quick brown
+                    fox juˇmps over
+                    the lazy dog
+                    "};
 
-//         // normal mode
-//         cx.set_shared_state(initial_state).await;
-//         cx.simulate_shared_keystrokes(["shift-s", "o"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             The quick brown
-//             oˇ
-//             the lazy dog
-//             "})
-//             .await;
+        // normal mode
+        cx.set_shared_state(initial_state).await;
+        cx.simulate_shared_keystrokes(["shift-s", "o"]).await;
+        cx.assert_shared_state(indoc! {"
+            The quick brown
+            oˇ
+            the lazy dog
+            "})
+            .await;
 
-//         // visual mode
-//         cx.set_shared_state(initial_state).await;
-//         cx.simulate_shared_keystrokes(["v", "k", "shift-s", "o"])
-//             .await;
-//         cx.assert_shared_state(indoc! {"
-//             oˇ
-//             the lazy dog
-//             "})
-//             .await;
+        // visual mode
+        cx.set_shared_state(initial_state).await;
+        cx.simulate_shared_keystrokes(["v", "k", "shift-s", "o"])
+            .await;
+        cx.assert_shared_state(indoc! {"
+            oˇ
+            the lazy dog
+            "})
+            .await;
 
-//         // visual block mode
-//         cx.set_shared_state(initial_state).await;
-//         cx.simulate_shared_keystrokes(["ctrl-v", "j", "shift-s", "o"])
-//             .await;
-//         cx.assert_shared_state(indoc! {"
-//             The quick brown
-//             oˇ
-//             "})
-//             .await;
+        // visual block mode
+        cx.set_shared_state(initial_state).await;
+        cx.simulate_shared_keystrokes(["ctrl-v", "j", "shift-s", "o"])
+            .await;
+        cx.assert_shared_state(indoc! {"
+            The quick brown
+            oˇ
+            "})
+            .await;
 
-//         // visual mode including newline
-//         cx.set_shared_state(initial_state).await;
-//         cx.simulate_shared_keystrokes(["v", "$", "shift-s", "o"])
-//             .await;
-//         cx.assert_shared_state(indoc! {"
-//             The quick brown
-//             oˇ
-//             the lazy dog
-//             "})
-//             .await;
+        // visual mode including newline
+        cx.set_shared_state(initial_state).await;
+        cx.simulate_shared_keystrokes(["v", "$", "shift-s", "o"])
+            .await;
+        cx.assert_shared_state(indoc! {"
+            The quick brown
+            oˇ
+            the lazy dog
+            "})
+            .await;
 
-//         // indentation
-//         cx.set_neovim_option("shiftwidth=4").await;
-//         cx.set_shared_state(initial_state).await;
-//         cx.simulate_shared_keystrokes([">", ">", "shift-s", "o"])
-//             .await;
-//         cx.assert_shared_state(indoc! {"
-//             The quick brown
-//                 oˇ
-//             the lazy dog
-//             "})
-//             .await;
-//     }
-// }
+        // indentation
+        cx.set_neovim_option("shiftwidth=4").await;
+        cx.set_shared_state(initial_state).await;
+        cx.simulate_shared_keystrokes([">", ">", "shift-s", "o"])
+            .await;
+        cx.assert_shared_state(indoc! {"
+            The quick brown
+                oˇ
+            the lazy dog
+            "})
+            .await;
+    }
+}

crates/vim2/src/object.rs 🔗

@@ -587,439 +587,439 @@ fn surrounding_markers(
     )
 }
 
-// #[cfg(test)]
-// mod test {
-//     use indoc::indoc;
-
-//     use crate::{
-//         state::Mode,
-//         test::{ExemptionFeatures, NeovimBackedTestContext, VimTestContext},
-//     };
-
-//     const WORD_LOCATIONS: &'static str = indoc! {"
-//         The quick ˇbrowˇnˇ•••
-//         fox ˇjuˇmpsˇ over
-//         the lazy dogˇ••
-//         ˇ
-//         ˇ
-//         ˇ
-//         Thˇeˇ-ˇquˇickˇ ˇbrownˇ•
-//         ˇ••
-//         ˇ••
-//         ˇ  fox-jumpˇs over
-//         the lazy dogˇ•
-//         ˇ
-//         "
-//     };
-
-//     #[gpui::test]
-//     async fn test_change_word_object(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.assert_binding_matches_all(["c", "i", "w"], WORD_LOCATIONS)
-//             .await;
-//         cx.assert_binding_matches_all(["c", "i", "shift-w"], WORD_LOCATIONS)
-//             .await;
-//         cx.assert_binding_matches_all(["c", "a", "w"], WORD_LOCATIONS)
-//             .await;
-//         cx.assert_binding_matches_all(["c", "a", "shift-w"], WORD_LOCATIONS)
-//             .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_delete_word_object(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.assert_binding_matches_all(["d", "i", "w"], WORD_LOCATIONS)
-//             .await;
-//         cx.assert_binding_matches_all(["d", "i", "shift-w"], WORD_LOCATIONS)
-//             .await;
-//         cx.assert_binding_matches_all(["d", "a", "w"], WORD_LOCATIONS)
-//             .await;
-//         cx.assert_binding_matches_all(["d", "a", "shift-w"], WORD_LOCATIONS)
-//             .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_visual_word_object(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         /*
-//                 cx.set_shared_state("The quick ˇbrown\nfox").await;
-//                 cx.simulate_shared_keystrokes(["v"]).await;
-//                 cx.assert_shared_state("The quick «bˇ»rown\nfox").await;
-//                 cx.simulate_shared_keystrokes(["i", "w"]).await;
-//                 cx.assert_shared_state("The quick «brownˇ»\nfox").await;
-//         */
-//         cx.set_shared_state("The quick brown\nˇ\nfox").await;
-//         cx.simulate_shared_keystrokes(["v"]).await;
-//         cx.assert_shared_state("The quick brown\n«\nˇ»fox").await;
-//         cx.simulate_shared_keystrokes(["i", "w"]).await;
-//         cx.assert_shared_state("The quick brown\n«\nˇ»fox").await;
-
-//         cx.assert_binding_matches_all(["v", "i", "w"], WORD_LOCATIONS)
-//             .await;
-//         cx.assert_binding_matches_all_exempted(
-//             ["v", "h", "i", "w"],
-//             WORD_LOCATIONS,
-//             ExemptionFeatures::NonEmptyVisualTextObjects,
-//         )
-//         .await;
-//         cx.assert_binding_matches_all_exempted(
-//             ["v", "l", "i", "w"],
-//             WORD_LOCATIONS,
-//             ExemptionFeatures::NonEmptyVisualTextObjects,
-//         )
-//         .await;
-//         cx.assert_binding_matches_all(["v", "i", "shift-w"], WORD_LOCATIONS)
-//             .await;
-
-//         cx.assert_binding_matches_all_exempted(
-//             ["v", "i", "h", "shift-w"],
-//             WORD_LOCATIONS,
-//             ExemptionFeatures::NonEmptyVisualTextObjects,
-//         )
-//         .await;
-//         cx.assert_binding_matches_all_exempted(
-//             ["v", "i", "l", "shift-w"],
-//             WORD_LOCATIONS,
-//             ExemptionFeatures::NonEmptyVisualTextObjects,
-//         )
-//         .await;
-
-//         cx.assert_binding_matches_all_exempted(
-//             ["v", "a", "w"],
-//             WORD_LOCATIONS,
-//             ExemptionFeatures::AroundObjectLeavesWhitespaceAtEndOfLine,
-//         )
-//         .await;
-//         cx.assert_binding_matches_all_exempted(
-//             ["v", "a", "shift-w"],
-//             WORD_LOCATIONS,
-//             ExemptionFeatures::AroundObjectLeavesWhitespaceAtEndOfLine,
-//         )
-//         .await;
-//     }
-
-//     const SENTENCE_EXAMPLES: &[&'static str] = &[
-//         "ˇThe quick ˇbrownˇ?ˇ ˇFox Jˇumpsˇ!ˇ Ovˇer theˇ lazyˇ.",
-//         indoc! {"
-//             ˇThe quick ˇbrownˇ
-//             fox jumps over
-//             the lazy doˇgˇ.ˇ ˇThe quick ˇ
-//             brown fox jumps over
-//         "},
-//         indoc! {"
-//             The quick brown fox jumps.
-//             Over the lazy dog
-//             ˇ
-//             ˇ
-//             ˇ  fox-jumpˇs over
-//             the lazy dog.ˇ
-//             ˇ
-//         "},
-//         r#"ˇThe ˇquick brownˇ.)ˇ]ˇ'ˇ" Brown ˇfox jumpsˇ.ˇ "#,
-//     ];
-
-//     #[gpui::test]
-//     async fn test_change_sentence_object(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx)
-//             .await
-//             .binding(["c", "i", "s"]);
-//         cx.add_initial_state_exemptions(
-//             "The quick brown fox jumps.\nOver the lazy dog\nˇ\nˇ\n  fox-jumps over\nthe lazy dog.\n\n",
-//             ExemptionFeatures::SentenceOnEmptyLines);
-//         cx.add_initial_state_exemptions(
-//             "The quick brown fox jumps.\nOver the lazy dog\n\n\nˇ  foxˇ-ˇjumpˇs over\nthe lazy dog.\n\n",
-//             ExemptionFeatures::SentenceAtStartOfLineWithWhitespace);
-//         cx.add_initial_state_exemptions(
-//             "The quick brown fox jumps.\nOver the lazy dog\n\n\n  fox-jumps over\nthe lazy dog.ˇ\nˇ\n",
-//             ExemptionFeatures::SentenceAfterPunctuationAtEndOfFile);
-//         for sentence_example in SENTENCE_EXAMPLES {
-//             cx.assert_all(sentence_example).await;
-//         }
-
-//         let mut cx = cx.binding(["c", "a", "s"]);
-//         cx.add_initial_state_exemptions(
-//             "The quick brown?ˇ Fox Jumps! Over the lazy.",
-//             ExemptionFeatures::IncorrectLandingPosition,
-//         );
-//         cx.add_initial_state_exemptions(
-//             "The quick brown.)]\'\" Brown fox jumps.ˇ ",
-//             ExemptionFeatures::AroundObjectLeavesWhitespaceAtEndOfLine,
-//         );
-
-//         for sentence_example in SENTENCE_EXAMPLES {
-//             cx.assert_all(sentence_example).await;
-//         }
-//     }
-
-//     #[gpui::test]
-//     async fn test_delete_sentence_object(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx)
-//             .await
-//             .binding(["d", "i", "s"]);
-//         cx.add_initial_state_exemptions(
-//             "The quick brown fox jumps.\nOver the lazy dog\nˇ\nˇ\n  fox-jumps over\nthe lazy dog.\n\n",
-//             ExemptionFeatures::SentenceOnEmptyLines);
-//         cx.add_initial_state_exemptions(
-//             "The quick brown fox jumps.\nOver the lazy dog\n\n\nˇ  foxˇ-ˇjumpˇs over\nthe lazy dog.\n\n",
-//             ExemptionFeatures::SentenceAtStartOfLineWithWhitespace);
-//         cx.add_initial_state_exemptions(
-//             "The quick brown fox jumps.\nOver the lazy dog\n\n\n  fox-jumps over\nthe lazy dog.ˇ\nˇ\n",
-//             ExemptionFeatures::SentenceAfterPunctuationAtEndOfFile);
-
-//         for sentence_example in SENTENCE_EXAMPLES {
-//             cx.assert_all(sentence_example).await;
-//         }
-
-//         let mut cx = cx.binding(["d", "a", "s"]);
-//         cx.add_initial_state_exemptions(
-//             "The quick brown?ˇ Fox Jumps! Over the lazy.",
-//             ExemptionFeatures::IncorrectLandingPosition,
-//         );
-//         cx.add_initial_state_exemptions(
-//             "The quick brown.)]\'\" Brown fox jumps.ˇ ",
-//             ExemptionFeatures::AroundObjectLeavesWhitespaceAtEndOfLine,
-//         );
-
-//         for sentence_example in SENTENCE_EXAMPLES {
-//             cx.assert_all(sentence_example).await;
-//         }
-//     }
-
-//     #[gpui::test]
-//     async fn test_visual_sentence_object(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx)
-//             .await
-//             .binding(["v", "i", "s"]);
-//         for sentence_example in SENTENCE_EXAMPLES {
-//             cx.assert_all_exempted(sentence_example, ExemptionFeatures::SentenceOnEmptyLines)
-//                 .await;
-//         }
-
-//         let mut cx = cx.binding(["v", "a", "s"]);
-//         for sentence_example in SENTENCE_EXAMPLES {
-//             cx.assert_all_exempted(
-//                 sentence_example,
-//                 ExemptionFeatures::AroundSentenceStartingBetweenIncludesWrongWhitespace,
-//             )
-//             .await;
-//         }
-//     }
-
-//     // Test string with "`" for opening surrounders and "'" for closing surrounders
-//     const SURROUNDING_MARKER_STRING: &str = indoc! {"
-//         ˇTh'ˇe ˇ`ˇ'ˇquˇi`ˇck broˇ'wn`
-//         'ˇfox juˇmps ovˇ`ˇer
-//         the ˇlazy dˇ'ˇoˇ`ˇg"};
-
-//     const SURROUNDING_OBJECTS: &[(char, char)] = &[
-//         ('\'', '\''), // Quote
-//         ('`', '`'),   // Back Quote
-//         ('"', '"'),   // Double Quote
-//         ('(', ')'),   // Parentheses
-//         ('[', ']'),   // SquareBrackets
-//         ('{', '}'),   // CurlyBrackets
-//         ('<', '>'),   // AngleBrackets
-//     ];
-
-//     #[gpui::test]
-//     async fn test_change_surrounding_character_objects(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         for (start, end) in SURROUNDING_OBJECTS {
-//             let marked_string = SURROUNDING_MARKER_STRING
-//                 .replace('`', &start.to_string())
-//                 .replace('\'', &end.to_string());
-
-//             cx.assert_binding_matches_all(["c", "i", &start.to_string()], &marked_string)
-//                 .await;
-//             cx.assert_binding_matches_all(["c", "i", &end.to_string()], &marked_string)
-//                 .await;
-//             cx.assert_binding_matches_all(["c", "a", &start.to_string()], &marked_string)
-//                 .await;
-//             cx.assert_binding_matches_all(["c", "a", &end.to_string()], &marked_string)
-//                 .await;
-//         }
-//     }
-//     #[gpui::test]
-//     async fn test_singleline_surrounding_character_objects(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-//         cx.set_shared_wrap(12).await;
-
-//         cx.set_shared_state(indoc! {
-//             "helˇlo \"world\"!"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["v", "i", "\""]).await;
-//         cx.assert_shared_state(indoc! {
-//             "hello \"«worldˇ»\"!"
-//         })
-//         .await;
-
-//         cx.set_shared_state(indoc! {
-//             "hello \"wˇorld\"!"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["v", "i", "\""]).await;
-//         cx.assert_shared_state(indoc! {
-//             "hello \"«worldˇ»\"!"
-//         })
-//         .await;
-
-//         cx.set_shared_state(indoc! {
-//             "hello \"wˇorld\"!"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["v", "a", "\""]).await;
-//         cx.assert_shared_state(indoc! {
-//             "hello« \"world\"ˇ»!"
-//         })
-//         .await;
-
-//         cx.set_shared_state(indoc! {
-//             "hello \"wˇorld\" !"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["v", "a", "\""]).await;
-//         cx.assert_shared_state(indoc! {
-//             "hello «\"world\" ˇ»!"
-//         })
-//         .await;
-
-//         cx.set_shared_state(indoc! {
-//             "hello \"wˇorld\"•
-//             goodbye"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["v", "a", "\""]).await;
-//         cx.assert_shared_state(indoc! {
-//             "hello «\"world\" ˇ»
-//             goodbye"
-//         })
-//         .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_multiline_surrounding_character_objects(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.set_shared_state(indoc! {
-//             "func empty(a string) bool {
-//                if a == \"\" {
-//                   return true
-//                }
-//                ˇreturn false
-//             }"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["v", "i", "{"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             func empty(a string) bool {
-//             «   if a == \"\" {
-//                   return true
-//                }
-//                return false
-//             ˇ»}"})
-//             .await;
-//         cx.set_shared_state(indoc! {
-//             "func empty(a string) bool {
-//                  if a == \"\" {
-//                      ˇreturn true
-//                  }
-//                  return false
-//             }"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["v", "i", "{"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             func empty(a string) bool {
-//                  if a == \"\" {
-//             «         return true
-//             ˇ»     }
-//                  return false
-//             }"})
-//             .await;
-
-//         cx.set_shared_state(indoc! {
-//             "func empty(a string) bool {
-//                  if a == \"\" ˇ{
-//                      return true
-//                  }
-//                  return false
-//             }"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["v", "i", "{"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             func empty(a string) bool {
-//                  if a == \"\" {
-//             «         return true
-//             ˇ»     }
-//                  return false
-//             }"})
-//             .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_vertical_bars(cx: &mut gpui::TestAppContext) {
-//         let mut cx = VimTestContext::new(cx, true).await;
-//         cx.set_state(
-//             indoc! {"
-//             fn boop() {
-//                 baz(ˇ|a, b| { bar(|j, k| { })})
-//             }"
-//             },
-//             Mode::Normal,
-//         );
-//         cx.simulate_keystrokes(["c", "i", "|"]);
-//         cx.assert_state(
-//             indoc! {"
-//             fn boop() {
-//                 baz(|ˇ| { bar(|j, k| { })})
-//             }"
-//             },
-//             Mode::Insert,
-//         );
-//         cx.simulate_keystrokes(["escape", "1", "8", "|"]);
-//         cx.assert_state(
-//             indoc! {"
-//             fn boop() {
-//                 baz(|| { bar(ˇ|j, k| { })})
-//             }"
-//             },
-//             Mode::Normal,
-//         );
-
-//         cx.simulate_keystrokes(["v", "a", "|"]);
-//         cx.assert_state(
-//             indoc! {"
-//             fn boop() {
-//                 baz(|| { bar(«|j, k| ˇ»{ })})
-//             }"
-//             },
-//             Mode::Visual,
-//         );
-//     }
-
-//     #[gpui::test]
-//     async fn test_delete_surrounding_character_objects(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         for (start, end) in SURROUNDING_OBJECTS {
-//             let marked_string = SURROUNDING_MARKER_STRING
-//                 .replace('`', &start.to_string())
-//                 .replace('\'', &end.to_string());
-
-//             cx.assert_binding_matches_all(["d", "i", &start.to_string()], &marked_string)
-//                 .await;
-//             cx.assert_binding_matches_all(["d", "i", &end.to_string()], &marked_string)
-//                 .await;
-//             cx.assert_binding_matches_all(["d", "a", &start.to_string()], &marked_string)
-//                 .await;
-//             cx.assert_binding_matches_all(["d", "a", &end.to_string()], &marked_string)
-//                 .await;
-//         }
-//     }
-// }
+#[cfg(test)]
+mod test {
+    use indoc::indoc;
+
+    use crate::{
+        state::Mode,
+        test::{ExemptionFeatures, NeovimBackedTestContext, VimTestContext},
+    };
+
+    const WORD_LOCATIONS: &'static str = indoc! {"
+        The quick ˇbrowˇnˇ•••
+        fox ˇjuˇmpsˇ over
+        the lazy dogˇ••
+        ˇ
+        ˇ
+        ˇ
+        Thˇeˇ-ˇquˇickˇ ˇbrownˇ•
+        ˇ••
+        ˇ••
+        ˇ  fox-jumpˇs over
+        the lazy dogˇ•
+        ˇ
+        "
+    };
+
+    #[gpui::test]
+    async fn test_change_word_object(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.assert_binding_matches_all(["c", "i", "w"], WORD_LOCATIONS)
+            .await;
+        cx.assert_binding_matches_all(["c", "i", "shift-w"], WORD_LOCATIONS)
+            .await;
+        cx.assert_binding_matches_all(["c", "a", "w"], WORD_LOCATIONS)
+            .await;
+        cx.assert_binding_matches_all(["c", "a", "shift-w"], WORD_LOCATIONS)
+            .await;
+    }
+
+    #[gpui::test]
+    async fn test_delete_word_object(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.assert_binding_matches_all(["d", "i", "w"], WORD_LOCATIONS)
+            .await;
+        cx.assert_binding_matches_all(["d", "i", "shift-w"], WORD_LOCATIONS)
+            .await;
+        cx.assert_binding_matches_all(["d", "a", "w"], WORD_LOCATIONS)
+            .await;
+        cx.assert_binding_matches_all(["d", "a", "shift-w"], WORD_LOCATIONS)
+            .await;
+    }
+
+    #[gpui::test]
+    async fn test_visual_word_object(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        /*
+                cx.set_shared_state("The quick ˇbrown\nfox").await;
+                cx.simulate_shared_keystrokes(["v"]).await;
+                cx.assert_shared_state("The quick «bˇ»rown\nfox").await;
+                cx.simulate_shared_keystrokes(["i", "w"]).await;
+                cx.assert_shared_state("The quick «brownˇ»\nfox").await;
+        */
+        cx.set_shared_state("The quick brown\nˇ\nfox").await;
+        cx.simulate_shared_keystrokes(["v"]).await;
+        cx.assert_shared_state("The quick brown\n«\nˇ»fox").await;
+        cx.simulate_shared_keystrokes(["i", "w"]).await;
+        cx.assert_shared_state("The quick brown\n«\nˇ»fox").await;
+
+        cx.assert_binding_matches_all(["v", "i", "w"], WORD_LOCATIONS)
+            .await;
+        cx.assert_binding_matches_all_exempted(
+            ["v", "h", "i", "w"],
+            WORD_LOCATIONS,
+            ExemptionFeatures::NonEmptyVisualTextObjects,
+        )
+        .await;
+        cx.assert_binding_matches_all_exempted(
+            ["v", "l", "i", "w"],
+            WORD_LOCATIONS,
+            ExemptionFeatures::NonEmptyVisualTextObjects,
+        )
+        .await;
+        cx.assert_binding_matches_all(["v", "i", "shift-w"], WORD_LOCATIONS)
+            .await;
+
+        cx.assert_binding_matches_all_exempted(
+            ["v", "i", "h", "shift-w"],
+            WORD_LOCATIONS,
+            ExemptionFeatures::NonEmptyVisualTextObjects,
+        )
+        .await;
+        cx.assert_binding_matches_all_exempted(
+            ["v", "i", "l", "shift-w"],
+            WORD_LOCATIONS,
+            ExemptionFeatures::NonEmptyVisualTextObjects,
+        )
+        .await;
+
+        cx.assert_binding_matches_all_exempted(
+            ["v", "a", "w"],
+            WORD_LOCATIONS,
+            ExemptionFeatures::AroundObjectLeavesWhitespaceAtEndOfLine,
+        )
+        .await;
+        cx.assert_binding_matches_all_exempted(
+            ["v", "a", "shift-w"],
+            WORD_LOCATIONS,
+            ExemptionFeatures::AroundObjectLeavesWhitespaceAtEndOfLine,
+        )
+        .await;
+    }
+
+    const SENTENCE_EXAMPLES: &[&'static str] = &[
+        "ˇThe quick ˇbrownˇ?ˇ ˇFox Jˇumpsˇ!ˇ Ovˇer theˇ lazyˇ.",
+        indoc! {"
+            ˇThe quick ˇbrownˇ
+            fox jumps over
+            the lazy doˇgˇ.ˇ ˇThe quick ˇ
+            brown fox jumps over
+        "},
+        indoc! {"
+            The quick brown fox jumps.
+            Over the lazy dog
+            ˇ
+            ˇ
+            ˇ  fox-jumpˇs over
+            the lazy dog.ˇ
+            ˇ
+        "},
+        r#"ˇThe ˇquick brownˇ.)ˇ]ˇ'ˇ" Brown ˇfox jumpsˇ.ˇ "#,
+    ];
+
+    #[gpui::test]
+    async fn test_change_sentence_object(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx)
+            .await
+            .binding(["c", "i", "s"]);
+        cx.add_initial_state_exemptions(
+            "The quick brown fox jumps.\nOver the lazy dog\nˇ\nˇ\n  fox-jumps over\nthe lazy dog.\n\n",
+            ExemptionFeatures::SentenceOnEmptyLines);
+        cx.add_initial_state_exemptions(
+            "The quick brown fox jumps.\nOver the lazy dog\n\n\nˇ  foxˇ-ˇjumpˇs over\nthe lazy dog.\n\n",
+            ExemptionFeatures::SentenceAtStartOfLineWithWhitespace);
+        cx.add_initial_state_exemptions(
+            "The quick brown fox jumps.\nOver the lazy dog\n\n\n  fox-jumps over\nthe lazy dog.ˇ\nˇ\n",
+            ExemptionFeatures::SentenceAfterPunctuationAtEndOfFile);
+        for sentence_example in SENTENCE_EXAMPLES {
+            cx.assert_all(sentence_example).await;
+        }
+
+        let mut cx = cx.binding(["c", "a", "s"]);
+        cx.add_initial_state_exemptions(
+            "The quick brown?ˇ Fox Jumps! Over the lazy.",
+            ExemptionFeatures::IncorrectLandingPosition,
+        );
+        cx.add_initial_state_exemptions(
+            "The quick brown.)]\'\" Brown fox jumps.ˇ ",
+            ExemptionFeatures::AroundObjectLeavesWhitespaceAtEndOfLine,
+        );
+
+        for sentence_example in SENTENCE_EXAMPLES {
+            cx.assert_all(sentence_example).await;
+        }
+    }
+
+    #[gpui::test]
+    async fn test_delete_sentence_object(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx)
+            .await
+            .binding(["d", "i", "s"]);
+        cx.add_initial_state_exemptions(
+            "The quick brown fox jumps.\nOver the lazy dog\nˇ\nˇ\n  fox-jumps over\nthe lazy dog.\n\n",
+            ExemptionFeatures::SentenceOnEmptyLines);
+        cx.add_initial_state_exemptions(
+            "The quick brown fox jumps.\nOver the lazy dog\n\n\nˇ  foxˇ-ˇjumpˇs over\nthe lazy dog.\n\n",
+            ExemptionFeatures::SentenceAtStartOfLineWithWhitespace);
+        cx.add_initial_state_exemptions(
+            "The quick brown fox jumps.\nOver the lazy dog\n\n\n  fox-jumps over\nthe lazy dog.ˇ\nˇ\n",
+            ExemptionFeatures::SentenceAfterPunctuationAtEndOfFile);
+
+        for sentence_example in SENTENCE_EXAMPLES {
+            cx.assert_all(sentence_example).await;
+        }
+
+        let mut cx = cx.binding(["d", "a", "s"]);
+        cx.add_initial_state_exemptions(
+            "The quick brown?ˇ Fox Jumps! Over the lazy.",
+            ExemptionFeatures::IncorrectLandingPosition,
+        );
+        cx.add_initial_state_exemptions(
+            "The quick brown.)]\'\" Brown fox jumps.ˇ ",
+            ExemptionFeatures::AroundObjectLeavesWhitespaceAtEndOfLine,
+        );
+
+        for sentence_example in SENTENCE_EXAMPLES {
+            cx.assert_all(sentence_example).await;
+        }
+    }
+
+    #[gpui::test]
+    async fn test_visual_sentence_object(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx)
+            .await
+            .binding(["v", "i", "s"]);
+        for sentence_example in SENTENCE_EXAMPLES {
+            cx.assert_all_exempted(sentence_example, ExemptionFeatures::SentenceOnEmptyLines)
+                .await;
+        }
+
+        let mut cx = cx.binding(["v", "a", "s"]);
+        for sentence_example in SENTENCE_EXAMPLES {
+            cx.assert_all_exempted(
+                sentence_example,
+                ExemptionFeatures::AroundSentenceStartingBetweenIncludesWrongWhitespace,
+            )
+            .await;
+        }
+    }
+
+    // Test string with "`" for opening surrounders and "'" for closing surrounders
+    const SURROUNDING_MARKER_STRING: &str = indoc! {"
+        ˇTh'ˇe ˇ`ˇ'ˇquˇi`ˇck broˇ'wn`
+        'ˇfox juˇmps ovˇ`ˇer
+        the ˇlazy dˇ'ˇoˇ`ˇg"};
+
+    const SURROUNDING_OBJECTS: &[(char, char)] = &[
+        ('\'', '\''), // Quote
+        ('`', '`'),   // Back Quote
+        ('"', '"'),   // Double Quote
+        ('(', ')'),   // Parentheses
+        ('[', ']'),   // SquareBrackets
+        ('{', '}'),   // CurlyBrackets
+        ('<', '>'),   // AngleBrackets
+    ];
+
+    #[gpui::test]
+    async fn test_change_surrounding_character_objects(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        for (start, end) in SURROUNDING_OBJECTS {
+            let marked_string = SURROUNDING_MARKER_STRING
+                .replace('`', &start.to_string())
+                .replace('\'', &end.to_string());
+
+            cx.assert_binding_matches_all(["c", "i", &start.to_string()], &marked_string)
+                .await;
+            cx.assert_binding_matches_all(["c", "i", &end.to_string()], &marked_string)
+                .await;
+            cx.assert_binding_matches_all(["c", "a", &start.to_string()], &marked_string)
+                .await;
+            cx.assert_binding_matches_all(["c", "a", &end.to_string()], &marked_string)
+                .await;
+        }
+    }
+    #[gpui::test]
+    async fn test_singleline_surrounding_character_objects(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+        cx.set_shared_wrap(12).await;
+
+        cx.set_shared_state(indoc! {
+            "helˇlo \"world\"!"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["v", "i", "\""]).await;
+        cx.assert_shared_state(indoc! {
+            "hello \"«worldˇ»\"!"
+        })
+        .await;
+
+        cx.set_shared_state(indoc! {
+            "hello \"wˇorld\"!"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["v", "i", "\""]).await;
+        cx.assert_shared_state(indoc! {
+            "hello \"«worldˇ»\"!"
+        })
+        .await;
+
+        cx.set_shared_state(indoc! {
+            "hello \"wˇorld\"!"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["v", "a", "\""]).await;
+        cx.assert_shared_state(indoc! {
+            "hello« \"world\"ˇ»!"
+        })
+        .await;
+
+        cx.set_shared_state(indoc! {
+            "hello \"wˇorld\" !"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["v", "a", "\""]).await;
+        cx.assert_shared_state(indoc! {
+            "hello «\"world\" ˇ»!"
+        })
+        .await;
+
+        cx.set_shared_state(indoc! {
+            "hello \"wˇorld\"•
+            goodbye"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["v", "a", "\""]).await;
+        cx.assert_shared_state(indoc! {
+            "hello «\"world\" ˇ»
+            goodbye"
+        })
+        .await;
+    }
+
+    #[gpui::test]
+    async fn test_multiline_surrounding_character_objects(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.set_shared_state(indoc! {
+            "func empty(a string) bool {
+               if a == \"\" {
+                  return true
+               }
+               ˇreturn false
+            }"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["v", "i", "{"]).await;
+        cx.assert_shared_state(indoc! {"
+            func empty(a string) bool {
+            «   if a == \"\" {
+                  return true
+               }
+               return false
+            ˇ»}"})
+            .await;
+        cx.set_shared_state(indoc! {
+            "func empty(a string) bool {
+                 if a == \"\" {
+                     ˇreturn true
+                 }
+                 return false
+            }"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["v", "i", "{"]).await;
+        cx.assert_shared_state(indoc! {"
+            func empty(a string) bool {
+                 if a == \"\" {
+            «         return true
+            ˇ»     }
+                 return false
+            }"})
+            .await;
+
+        cx.set_shared_state(indoc! {
+            "func empty(a string) bool {
+                 if a == \"\" ˇ{
+                     return true
+                 }
+                 return false
+            }"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["v", "i", "{"]).await;
+        cx.assert_shared_state(indoc! {"
+            func empty(a string) bool {
+                 if a == \"\" {
+            «         return true
+            ˇ»     }
+                 return false
+            }"})
+            .await;
+    }
+
+    #[gpui::test]
+    async fn test_vertical_bars(cx: &mut gpui::TestAppContext) {
+        let mut cx = VimTestContext::new(cx, true).await;
+        cx.set_state(
+            indoc! {"
+            fn boop() {
+                baz(ˇ|a, b| { bar(|j, k| { })})
+            }"
+            },
+            Mode::Normal,
+        );
+        cx.simulate_keystrokes(["c", "i", "|"]);
+        cx.assert_state(
+            indoc! {"
+            fn boop() {
+                baz(|ˇ| { bar(|j, k| { })})
+            }"
+            },
+            Mode::Insert,
+        );
+        cx.simulate_keystrokes(["escape", "1", "8", "|"]);
+        cx.assert_state(
+            indoc! {"
+            fn boop() {
+                baz(|| { bar(ˇ|j, k| { })})
+            }"
+            },
+            Mode::Normal,
+        );
+
+        cx.simulate_keystrokes(["v", "a", "|"]);
+        cx.assert_state(
+            indoc! {"
+            fn boop() {
+                baz(|| { bar(«|j, k| ˇ»{ })})
+            }"
+            },
+            Mode::Visual,
+        );
+    }
+
+    #[gpui::test]
+    async fn test_delete_surrounding_character_objects(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        for (start, end) in SURROUNDING_OBJECTS {
+            let marked_string = SURROUNDING_MARKER_STRING
+                .replace('`', &start.to_string())
+                .replace('\'', &end.to_string());
+
+            cx.assert_binding_matches_all(["d", "i", &start.to_string()], &marked_string)
+                .await;
+            cx.assert_binding_matches_all(["d", "i", &end.to_string()], &marked_string)
+                .await;
+            cx.assert_binding_matches_all(["d", "a", &start.to_string()], &marked_string)
+                .await;
+            cx.assert_binding_matches_all(["d", "a", &end.to_string()], &marked_string)
+                .await;
+        }
+    }
+}

crates/vim2/src/test/neovim_backed_test_context.rs 🔗

@@ -2,6 +2,7 @@
 // todo!()
 
 use editor::{scroll::VERTICAL_SCROLL_MARGIN, test::editor_test_context::ContextHandle};
+use gpui::{point, px, rems, size, Context};
 use indoc::indoc;
 use settings::SettingsStore;
 use std::{
@@ -153,20 +154,36 @@ impl<'a> NeovimBackedTestContext<'a> {
         })
     }
 
-    // todo!()
-    // pub async fn set_scroll_height(&mut self, rows: u32) {
-    //     // match Zed's scrolling behavior
-    //     self.neovim
-    //         .set_option(&format!("scrolloff={}", VERTICAL_SCROLL_MARGIN))
-    //         .await;
-    //     // +2 to account for the vim command UI at the bottom.
-    //     self.neovim.set_option(&format!("lines={}", rows + 2)).await;
-    //     let window = self.window;
-    //     let line_height =
-    //         self.editor(|editor, cx| editor.style().text.line_height(cx.font_cache()));
-
-    //     window.simulate_resize(vec2f(1000., (rows as f32) * line_height), &mut self.cx);
-    // }
+    pub async fn set_scroll_height(&mut self, rows: u32) {
+        // match Zed's scrolling behavior
+        self.neovim
+            .set_option(&format!("scrolloff={}", VERTICAL_SCROLL_MARGIN))
+            .await;
+        // +2 to account for the vim command UI at the bottom.
+        self.neovim.set_option(&format!("lines={}", rows + 2)).await;
+        let (line_height, visible_line_count) = self.editor(|editor, cx| {
+            (
+                editor
+                    .style()
+                    .unwrap()
+                    .text
+                    .line_height_in_pixels(cx.rem_size()),
+                editor.visible_line_count().unwrap(),
+            )
+        });
+
+        let window = self.window;
+        let margin = self
+            .update_window(window, |_, cx| {
+                cx.viewport_size().height - line_height * visible_line_count
+            })
+            .unwrap();
+
+        self.simulate_window_resize(
+            self.window,
+            size(px(1000.), margin + (rows as f32) * line_height),
+        );
+    }
 
     pub async fn set_neovim_option(&mut self, option: &str) {
         self.neovim.set_option(option).await;

crates/vim2/src/test/vim_test_context.rs 🔗

@@ -18,7 +18,11 @@ pub struct VimTestContext<'a> {
 }
 
 impl<'a> VimTestContext<'a> {
-    pub async fn new(cx: &'a mut gpui::TestAppContext, enabled: bool) -> VimTestContext<'a> {
+    pub fn init(cx: &mut gpui::TestAppContext) {
+        if cx.has_global::<Vim>() {
+            dbg!("OOPS");
+            return;
+        }
         cx.update(|cx| {
             search::init(cx);
             let settings = SettingsStore::test(cx);
@@ -26,18 +30,16 @@ impl<'a> VimTestContext<'a> {
             command_palette::init(cx);
             crate::init(cx);
         });
+    }
+
+    pub async fn new(cx: &'a mut gpui::TestAppContext, enabled: bool) -> VimTestContext<'a> {
+        Self::init(cx);
         let lsp = EditorLspTestContext::new_rust(Default::default(), cx).await;
         Self::new_with_lsp(lsp, enabled)
     }
 
     pub async fn new_typescript(cx: &'a mut gpui::TestAppContext) -> VimTestContext<'a> {
-        cx.update(|cx| {
-            search::init(cx);
-            let settings = SettingsStore::test(cx);
-            cx.set_global(settings);
-            command_palette::init(cx);
-            crate::init(cx);
-        });
+        Self::init(cx);
         Self::new_with_lsp(
             EditorLspTestContext::new_typescript(Default::default(), cx).await,
             true,

crates/vim2/src/vim.rs 🔗

@@ -140,6 +140,8 @@ pub fn observe_keystrokes(cx: &mut WindowContext) {
             if action.name().starts_with("vim::") {
                 return;
             }
+        } else if cx.has_pending_keystrokes() {
+            return;
         }
 
         Vim::update(cx, |vim, cx| match vim.active_operator() {

crates/vim2/src/visual.rs 🔗

@@ -463,567 +463,572 @@ pub fn select_previous(
     .unwrap_or(Ok(()))
 }
 
-// #[cfg(test)]
-// mod test {
-//     use indoc::indoc;
-//     use workspace::item::Item;
-
-//     use crate::{
-//         state::Mode,
-//         test::{NeovimBackedTestContext, VimTestContext},
-//     };
-
-//     #[gpui::test]
-//     async fn test_enter_visual_mode(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.set_shared_state(indoc! {
-//             "The ˇquick brown
-//             fox jumps over
-//             the lazy dog"
-//         })
-//         .await;
-//         let cursor = cx.update_editor(|editor, cx| editor.pixel_position_of_cursor(cx));
-
-//         // entering visual mode should select the character
-//         // under cursor
-//         cx.simulate_shared_keystrokes(["v"]).await;
-//         cx.assert_shared_state(indoc! { "The «qˇ»uick brown
-//             fox jumps over
-//             the lazy dog"})
-//             .await;
-//         cx.update_editor(|editor, cx| assert_eq!(cursor, editor.pixel_position_of_cursor(cx)));
-
-//         // forwards motions should extend the selection
-//         cx.simulate_shared_keystrokes(["w", "j"]).await;
-//         cx.assert_shared_state(indoc! { "The «quick brown
-//             fox jumps oˇ»ver
-//             the lazy dog"})
-//             .await;
-
-//         cx.simulate_shared_keystrokes(["escape"]).await;
-//         assert_eq!(Mode::Normal, cx.neovim_mode().await);
-//         cx.assert_shared_state(indoc! { "The quick brown
-//             fox jumps ˇover
-//             the lazy dog"})
-//             .await;
-
-//         // motions work backwards
-//         cx.simulate_shared_keystrokes(["v", "k", "b"]).await;
-//         cx.assert_shared_state(indoc! { "The «ˇquick brown
-//             fox jumps o»ver
-//             the lazy dog"})
-//             .await;
-
-//         // works on empty lines
-//         cx.set_shared_state(indoc! {"
-//             a
-//             ˇ
-//             b
-//             "})
-//             .await;
-//         let cursor = cx.update_editor(|editor, cx| editor.pixel_position_of_cursor(cx));
-//         cx.simulate_shared_keystrokes(["v"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             a
-//             «
-//             ˇ»b
-//         "})
-//             .await;
-//         cx.update_editor(|editor, cx| assert_eq!(cursor, editor.pixel_position_of_cursor(cx)));
-
-//         // toggles off again
-//         cx.simulate_shared_keystrokes(["v"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             a
-//             ˇ
-//             b
-//             "})
-//             .await;
-
-//         // works at the end of a document
-//         cx.set_shared_state(indoc! {"
-//             a
-//             b
-//             ˇ"})
-//             .await;
-
-//         cx.simulate_shared_keystrokes(["v"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             a
-//             b
-//             ˇ"})
-//             .await;
-//         assert_eq!(cx.mode(), cx.neovim_mode().await);
-//     }
-
-//     #[gpui::test]
-//     async fn test_enter_visual_line_mode(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.set_shared_state(indoc! {
-//             "The ˇquick brown
-//             fox jumps over
-//             the lazy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["shift-v"]).await;
-//         cx.assert_shared_state(indoc! { "The «qˇ»uick brown
-//             fox jumps over
-//             the lazy dog"})
-//             .await;
-//         assert_eq!(cx.mode(), cx.neovim_mode().await);
-//         cx.simulate_shared_keystrokes(["x"]).await;
-//         cx.assert_shared_state(indoc! { "fox ˇjumps over
-//         the lazy dog"})
-//             .await;
-
-//         // it should work on empty lines
-//         cx.set_shared_state(indoc! {"
-//             a
-//             ˇ
-//             b"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["shift-v"]).await;
-//         cx.assert_shared_state(indoc! { "
-//             a
-//             «
-//             ˇ»b"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["x"]).await;
-//         cx.assert_shared_state(indoc! { "
-//             a
-//             ˇb"})
-//             .await;
-
-//         // it should work at the end of the document
-//         cx.set_shared_state(indoc! {"
-//             a
-//             b
-//             ˇ"})
-//             .await;
-//         let cursor = cx.update_editor(|editor, cx| editor.pixel_position_of_cursor(cx));
-//         cx.simulate_shared_keystrokes(["shift-v"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             a
-//             b
-//             ˇ"})
-//             .await;
-//         assert_eq!(cx.mode(), cx.neovim_mode().await);
-//         cx.update_editor(|editor, cx| assert_eq!(cursor, editor.pixel_position_of_cursor(cx)));
-//         cx.simulate_shared_keystrokes(["x"]).await;
-//         cx.assert_shared_state(indoc! {"
-//             a
-//             ˇb"})
-//             .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_visual_delete(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.assert_binding_matches(["v", "w"], "The quick ˇbrown")
-//             .await;
-
-//         cx.assert_binding_matches(["v", "w", "x"], "The quick ˇbrown")
-//             .await;
-//         cx.assert_binding_matches(
-//             ["v", "w", "j", "x"],
-//             indoc! {"
-//                 The ˇquick brown
-//                 fox jumps over
-//                 the lazy dog"},
-//         )
-//         .await;
-//         // Test pasting code copied on delete
-//         cx.simulate_shared_keystrokes(["j", "p"]).await;
-//         cx.assert_state_matches().await;
-
-//         let mut cx = cx.binding(["v", "w", "j", "x"]);
-//         cx.assert_all(indoc! {"
-//                 The ˇquick brown
-//                 fox jumps over
-//                 the ˇlazy dog"})
-//             .await;
-//         let mut cx = cx.binding(["v", "b", "k", "x"]);
-//         cx.assert_all(indoc! {"
-//                 The ˇquick brown
-//                 fox jumps ˇover
-//                 the ˇlazy dog"})
-//             .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_visual_line_delete(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.set_shared_state(indoc! {"
-//                 The quˇick brown
-//                 fox jumps over
-//                 the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["shift-v", "x"]).await;
-//         cx.assert_state_matches().await;
-
-//         // Test pasting code copied on delete
-//         cx.simulate_shared_keystroke("p").await;
-//         cx.assert_state_matches().await;
-
-//         cx.set_shared_state(indoc! {"
-//                 The quick brown
-//                 fox jumps over
-//                 the laˇzy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["shift-v", "x"]).await;
-//         cx.assert_state_matches().await;
-//         cx.assert_shared_clipboard("the lazy dog\n").await;
-
-//         for marked_text in cx.each_marked_position(indoc! {"
-//                         The quˇick brown
-//                         fox jumps over
-//                         the lazy dog"})
-//         {
-//             cx.set_shared_state(&marked_text).await;
-//             cx.simulate_shared_keystrokes(["shift-v", "j", "x"]).await;
-//             cx.assert_state_matches().await;
-//             // Test pasting code copied on delete
-//             cx.simulate_shared_keystroke("p").await;
-//             cx.assert_state_matches().await;
-//         }
-
-//         cx.set_shared_state(indoc! {"
-//             The ˇlong line
-//             should not
-//             crash
-//             "})
-//             .await;
-//         cx.simulate_shared_keystrokes(["shift-v", "$", "x"]).await;
-//         cx.assert_state_matches().await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_visual_yank(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.set_shared_state("The quick ˇbrown").await;
-//         cx.simulate_shared_keystrokes(["v", "w", "y"]).await;
-//         cx.assert_shared_state("The quick ˇbrown").await;
-//         cx.assert_shared_clipboard("brown").await;
-
-//         cx.set_shared_state(indoc! {"
-//                 The ˇquick brown
-//                 fox jumps over
-//                 the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["v", "w", "j", "y"]).await;
-//         cx.assert_shared_state(indoc! {"
-//                     The ˇquick brown
-//                     fox jumps over
-//                     the lazy dog"})
-//             .await;
-//         cx.assert_shared_clipboard(indoc! {"
-//                 quick brown
-//                 fox jumps o"})
-//             .await;
-
-//         cx.set_shared_state(indoc! {"
-//                     The quick brown
-//                     fox jumps over
-//                     the ˇlazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["v", "w", "j", "y"]).await;
-//         cx.assert_shared_state(indoc! {"
-//                     The quick brown
-//                     fox jumps over
-//                     the ˇlazy dog"})
-//             .await;
-//         cx.assert_shared_clipboard("lazy d").await;
-//         cx.simulate_shared_keystrokes(["shift-v", "y"]).await;
-//         cx.assert_shared_clipboard("the lazy dog\n").await;
-
-//         let mut cx = cx.binding(["v", "b", "k", "y"]);
-//         cx.set_shared_state(indoc! {"
-//                     The ˇquick brown
-//                     fox jumps over
-//                     the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["v", "b", "k", "y"]).await;
-//         cx.assert_shared_state(indoc! {"
-//                     ˇThe quick brown
-//                     fox jumps over
-//                     the lazy dog"})
-//             .await;
-//         cx.assert_clipboard_content(Some("The q"));
-
-//         cx.set_shared_state(indoc! {"
-//                     The quick brown
-//                     fox ˇjumps over
-//                     the lazy dog"})
-//             .await;
-//         cx.simulate_shared_keystrokes(["shift-v", "shift-g", "shift-y"])
-//             .await;
-//         cx.assert_shared_state(indoc! {"
-//                     The quick brown
-//                     ˇfox jumps over
-//                     the lazy dog"})
-//             .await;
-//         cx.assert_shared_clipboard("fox jumps over\nthe lazy dog\n")
-//             .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_visual_block_mode(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.set_shared_state(indoc! {
-//             "The ˇquick brown
-//              fox jumps over
-//              the lazy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["ctrl-v"]).await;
-//         cx.assert_shared_state(indoc! {
-//             "The «qˇ»uick brown
-//             fox jumps over
-//             the lazy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["2", "down"]).await;
-//         cx.assert_shared_state(indoc! {
-//             "The «qˇ»uick brown
-//             fox «jˇ»umps over
-//             the «lˇ»azy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["e"]).await;
-//         cx.assert_shared_state(indoc! {
-//             "The «quicˇ»k brown
-//             fox «jumpˇ»s over
-//             the «lazyˇ» dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["^"]).await;
-//         cx.assert_shared_state(indoc! {
-//             "«ˇThe q»uick brown
-//             «ˇfox j»umps over
-//             «ˇthe l»azy dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["$"]).await;
-//         cx.assert_shared_state(indoc! {
-//             "The «quick brownˇ»
-//             fox «jumps overˇ»
-//             the «lazy dogˇ»"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["shift-f", " "]).await;
-//         cx.assert_shared_state(indoc! {
-//             "The «quickˇ» brown
-//             fox «jumpsˇ» over
-//             the «lazy ˇ»dog"
-//         })
-//         .await;
-
-//         // toggling through visual mode works as expected
-//         cx.simulate_shared_keystrokes(["v"]).await;
-//         cx.assert_shared_state(indoc! {
-//             "The «quick brown
-//             fox jumps over
-//             the lazy ˇ»dog"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["ctrl-v"]).await;
-//         cx.assert_shared_state(indoc! {
-//             "The «quickˇ» brown
-//             fox «jumpsˇ» over
-//             the «lazy ˇ»dog"
-//         })
-//         .await;
-
-//         cx.set_shared_state(indoc! {
-//             "The ˇquick
-//              brown
-//              fox
-//              jumps over the
-
-//              lazy dog
-//             "
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["ctrl-v", "down", "down"])
-//             .await;
-//         cx.assert_shared_state(indoc! {
-//             "The«ˇ q»uick
-//             bro«ˇwn»
-//             foxˇ
-//             jumps over the
-
-//             lazy dog
-//             "
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["down"]).await;
-//         cx.assert_shared_state(indoc! {
-//             "The «qˇ»uick
-//             brow«nˇ»
-//             fox
-//             jump«sˇ» over the
-
-//             lazy dog
-//             "
-//         })
-//         .await;
-//         cx.simulate_shared_keystroke("left").await;
-//         cx.assert_shared_state(indoc! {
-//             "The«ˇ q»uick
-//             bro«ˇwn»
-//             foxˇ
-//             jum«ˇps» over the
-
-//             lazy dog
-//             "
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["s", "o", "escape"]).await;
-//         cx.assert_shared_state(indoc! {
-//             "Theˇouick
-//             broo
-//             foxo
-//             jumo over the
-
-//             lazy dog
-//             "
-//         })
-//         .await;
-
-//         //https://github.com/zed-industries/community/issues/1950
-//         cx.set_shared_state(indoc! {
-//             "Theˇ quick brown
-
-//             fox jumps over
-//             the lazy dog
-//             "
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["l", "ctrl-v", "j", "j"])
-//             .await;
-//         cx.assert_shared_state(indoc! {
-//             "The «qˇ»uick brown
-
-//             fox «jˇ»umps over
-//             the lazy dog
-//             "
-//         })
-//         .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_visual_block_issue_2123(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.set_shared_state(indoc! {
-//             "The ˇquick brown
-//             fox jumps over
-//             the lazy dog
-//             "
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["ctrl-v", "right", "down"])
-//             .await;
-//         cx.assert_shared_state(indoc! {
-//             "The «quˇ»ick brown
-//             fox «juˇ»mps over
-//             the lazy dog
-//             "
-//         })
-//         .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_visual_block_insert(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.set_shared_state(indoc! {
-//             "ˇThe quick brown
-//             fox jumps over
-//             the lazy dog
-//             "
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["ctrl-v", "9", "down"]).await;
-//         cx.assert_shared_state(indoc! {
-//             "«Tˇ»he quick brown
-//             «fˇ»ox jumps over
-//             «tˇ»he lazy dog
-//             ˇ"
-//         })
-//         .await;
-
-//         cx.simulate_shared_keystrokes(["shift-i", "k", "escape"])
-//             .await;
-//         cx.assert_shared_state(indoc! {
-//             "ˇkThe quick brown
-//             kfox jumps over
-//             kthe lazy dog
-//             k"
-//         })
-//         .await;
-
-//         cx.set_shared_state(indoc! {
-//             "ˇThe quick brown
-//             fox jumps over
-//             the lazy dog
-//             "
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["ctrl-v", "9", "down"]).await;
-//         cx.assert_shared_state(indoc! {
-//             "«Tˇ»he quick brown
-//             «fˇ»ox jumps over
-//             «tˇ»he lazy dog
-//             ˇ"
-//         })
-//         .await;
-//         cx.simulate_shared_keystrokes(["c", "k", "escape"]).await;
-//         cx.assert_shared_state(indoc! {
-//             "ˇkhe quick brown
-//             kox jumps over
-//             khe lazy dog
-//             k"
-//         })
-//         .await;
-//     }
-
-//     #[gpui::test]
-//     async fn test_visual_object(cx: &mut gpui::TestAppContext) {
-//         let mut cx = NeovimBackedTestContext::new(cx).await;
-
-//         cx.set_shared_state("hello (in [parˇens] o)").await;
-//         cx.simulate_shared_keystrokes(["ctrl-v", "l"]).await;
-//         cx.simulate_shared_keystrokes(["a", "]"]).await;
-//         cx.assert_shared_state("hello (in «[parens]ˇ» o)").await;
-//         assert_eq!(cx.mode(), Mode::Visual);
-//         cx.simulate_shared_keystrokes(["i", "("]).await;
-//         cx.assert_shared_state("hello («in [parens] oˇ»)").await;
-
-//         cx.set_shared_state("hello in a wˇord again.").await;
-//         cx.simulate_shared_keystrokes(["ctrl-v", "l", "i", "w"])
-//             .await;
-//         cx.assert_shared_state("hello in a w«ordˇ» again.").await;
-//         assert_eq!(cx.mode(), Mode::VisualBlock);
-//         cx.simulate_shared_keystrokes(["o", "a", "s"]).await;
-//         cx.assert_shared_state("«ˇhello in a word» again.").await;
-//         assert_eq!(cx.mode(), Mode::Visual);
-//     }
-
-//     #[gpui::test]
-//     async fn test_mode_across_command(cx: &mut gpui::TestAppContext) {
-//         let mut cx = VimTestContext::new(cx, true).await;
-
-//         cx.set_state("aˇbc", Mode::Normal);
-//         cx.simulate_keystrokes(["ctrl-v"]);
-//         assert_eq!(cx.mode(), Mode::VisualBlock);
-//         cx.simulate_keystrokes(["cmd-shift-p", "escape"]);
-//         assert_eq!(cx.mode(), Mode::VisualBlock);
-//     }
-// }
+#[cfg(test)]
+mod test {
+    use indoc::indoc;
+    use workspace::item::Item;
+
+    use crate::{
+        state::Mode,
+        test::{NeovimBackedTestContext, VimTestContext},
+    };
+
+    #[gpui::test]
+    async fn test_enter_visual_mode(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.set_shared_state(indoc! {
+            "The ˇquick brown
+            fox jumps over
+            the lazy dog"
+        })
+        .await;
+        let cursor = cx.update_editor(|editor, cx| editor.pixel_position_of_cursor(cx));
+
+        // entering visual mode should select the character
+        // under cursor
+        cx.simulate_shared_keystrokes(["v"]).await;
+        cx.assert_shared_state(indoc! { "The «qˇ»uick brown
+            fox jumps over
+            the lazy dog"})
+            .await;
+        cx.update_editor(|editor, cx| assert_eq!(cursor, editor.pixel_position_of_cursor(cx)));
+
+        // forwards motions should extend the selection
+        cx.simulate_shared_keystrokes(["w", "j"]).await;
+        cx.assert_shared_state(indoc! { "The «quick brown
+            fox jumps oˇ»ver
+            the lazy dog"})
+            .await;
+
+        cx.simulate_shared_keystrokes(["escape"]).await;
+        assert_eq!(Mode::Normal, cx.neovim_mode().await);
+        cx.assert_shared_state(indoc! { "The quick brown
+            fox jumps ˇover
+            the lazy dog"})
+            .await;
+
+        // motions work backwards
+        cx.simulate_shared_keystrokes(["v", "k", "b"]).await;
+        cx.assert_shared_state(indoc! { "The «ˇquick brown
+            fox jumps o»ver
+            the lazy dog"})
+            .await;
+
+        // works on empty lines
+        cx.set_shared_state(indoc! {"
+            a
+            ˇ
+            b
+            "})
+            .await;
+        let cursor = cx.update_editor(|editor, cx| editor.pixel_position_of_cursor(cx));
+        cx.simulate_shared_keystrokes(["v"]).await;
+        cx.assert_shared_state(indoc! {"
+            a
+            «
+            ˇ»b
+        "})
+            .await;
+        cx.update_editor(|editor, cx| assert_eq!(cursor, editor.pixel_position_of_cursor(cx)));
+
+        // toggles off again
+        cx.simulate_shared_keystrokes(["v"]).await;
+        cx.assert_shared_state(indoc! {"
+            a
+            ˇ
+            b
+            "})
+            .await;
+
+        // works at the end of a document
+        cx.set_shared_state(indoc! {"
+            a
+            b
+            ˇ"})
+            .await;
+
+        cx.simulate_shared_keystrokes(["v"]).await;
+        cx.assert_shared_state(indoc! {"
+            a
+            b
+            ˇ"})
+            .await;
+        assert_eq!(cx.mode(), cx.neovim_mode().await);
+    }
+
+    #[gpui::test]
+    async fn test_enter_visual_line_mode(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.set_shared_state(indoc! {
+            "The ˇquick brown
+            fox jumps over
+            the lazy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["shift-v"]).await;
+        cx.assert_shared_state(indoc! { "The «qˇ»uick brown
+            fox jumps over
+            the lazy dog"})
+            .await;
+        assert_eq!(cx.mode(), cx.neovim_mode().await);
+        cx.simulate_shared_keystrokes(["x"]).await;
+        cx.assert_shared_state(indoc! { "fox ˇjumps over
+        the lazy dog"})
+            .await;
+
+        // it should work on empty lines
+        cx.set_shared_state(indoc! {"
+            a
+            ˇ
+            b"})
+            .await;
+        cx.simulate_shared_keystrokes(["shift-v"]).await;
+        cx.assert_shared_state(indoc! { "
+            a
+            «
+            ˇ»b"})
+            .await;
+        cx.simulate_shared_keystrokes(["x"]).await;
+        cx.assert_shared_state(indoc! { "
+            a
+            ˇb"})
+            .await;
+
+        // it should work at the end of the document
+        cx.set_shared_state(indoc! {"
+            a
+            b
+            ˇ"})
+            .await;
+        let cursor = cx.update_editor(|editor, cx| editor.pixel_position_of_cursor(cx));
+        cx.simulate_shared_keystrokes(["shift-v"]).await;
+        cx.assert_shared_state(indoc! {"
+            a
+            b
+            ˇ"})
+            .await;
+        assert_eq!(cx.mode(), cx.neovim_mode().await);
+        cx.update_editor(|editor, cx| assert_eq!(cursor, editor.pixel_position_of_cursor(cx)));
+        cx.simulate_shared_keystrokes(["x"]).await;
+        cx.assert_shared_state(indoc! {"
+            a
+            ˇb"})
+            .await;
+    }
+
+    #[gpui::test]
+    async fn test_visual_delete(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.assert_binding_matches(["v", "w"], "The quick ˇbrown")
+            .await;
+
+        cx.assert_binding_matches(["v", "w", "x"], "The quick ˇbrown")
+            .await;
+        cx.assert_binding_matches(
+            ["v", "w", "j", "x"],
+            indoc! {"
+                The ˇquick brown
+                fox jumps over
+                the lazy dog"},
+        )
+        .await;
+        // Test pasting code copied on delete
+        cx.simulate_shared_keystrokes(["j", "p"]).await;
+        cx.assert_state_matches().await;
+
+        let mut cx = cx.binding(["v", "w", "j", "x"]);
+        cx.assert_all(indoc! {"
+                The ˇquick brown
+                fox jumps over
+                the ˇlazy dog"})
+            .await;
+        let mut cx = cx.binding(["v", "b", "k", "x"]);
+        cx.assert_all(indoc! {"
+                The ˇquick brown
+                fox jumps ˇover
+                the ˇlazy dog"})
+            .await;
+    }
+
+    #[gpui::test]
+    async fn test_visual_line_delete(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.set_shared_state(indoc! {"
+                The quˇick brown
+                fox jumps over
+                the lazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["shift-v", "x"]).await;
+        cx.assert_state_matches().await;
+
+        // Test pasting code copied on delete
+        cx.simulate_shared_keystroke("p").await;
+        cx.assert_state_matches().await;
+
+        cx.set_shared_state(indoc! {"
+                The quick brown
+                fox jumps over
+                the laˇzy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["shift-v", "x"]).await;
+        cx.assert_state_matches().await;
+        cx.assert_shared_clipboard("the lazy dog\n").await;
+
+        for marked_text in cx.each_marked_position(indoc! {"
+                        The quˇick brown
+                        fox jumps over
+                        the lazy dog"})
+        {
+            cx.set_shared_state(&marked_text).await;
+            cx.simulate_shared_keystrokes(["shift-v", "j", "x"]).await;
+            cx.assert_state_matches().await;
+            // Test pasting code copied on delete
+            cx.simulate_shared_keystroke("p").await;
+            cx.assert_state_matches().await;
+        }
+
+        cx.set_shared_state(indoc! {"
+            The ˇlong line
+            should not
+            crash
+            "})
+            .await;
+        cx.simulate_shared_keystrokes(["shift-v", "$", "x"]).await;
+        cx.assert_state_matches().await;
+    }
+
+    #[gpui::test]
+    async fn test_visual_yank(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.set_shared_state("The quick ˇbrown").await;
+        cx.simulate_shared_keystrokes(["v", "w", "y"]).await;
+        cx.assert_shared_state("The quick ˇbrown").await;
+        cx.assert_shared_clipboard("brown").await;
+
+        cx.set_shared_state(indoc! {"
+                The ˇquick brown
+                fox jumps over
+                the lazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["v", "w", "j", "y"]).await;
+        cx.assert_shared_state(indoc! {"
+                    The ˇquick brown
+                    fox jumps over
+                    the lazy dog"})
+            .await;
+        cx.assert_shared_clipboard(indoc! {"
+                quick brown
+                fox jumps o"})
+            .await;
+
+        cx.set_shared_state(indoc! {"
+                    The quick brown
+                    fox jumps over
+                    the ˇlazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["v", "w", "j", "y"]).await;
+        cx.assert_shared_state(indoc! {"
+                    The quick brown
+                    fox jumps over
+                    the ˇlazy dog"})
+            .await;
+        cx.assert_shared_clipboard("lazy d").await;
+        cx.simulate_shared_keystrokes(["shift-v", "y"]).await;
+        cx.assert_shared_clipboard("the lazy dog\n").await;
+
+        let mut cx = cx.binding(["v", "b", "k", "y"]);
+        cx.set_shared_state(indoc! {"
+                    The ˇquick brown
+                    fox jumps over
+                    the lazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["v", "b", "k", "y"]).await;
+        cx.assert_shared_state(indoc! {"
+                    ˇThe quick brown
+                    fox jumps over
+                    the lazy dog"})
+            .await;
+        assert_eq!(
+            cx.read_from_clipboard()
+                .map(|item| item.text().clone())
+                .unwrap(),
+            "The q"
+        );
+
+        cx.set_shared_state(indoc! {"
+                    The quick brown
+                    fox ˇjumps over
+                    the lazy dog"})
+            .await;
+        cx.simulate_shared_keystrokes(["shift-v", "shift-g", "shift-y"])
+            .await;
+        cx.assert_shared_state(indoc! {"
+                    The quick brown
+                    ˇfox jumps over
+                    the lazy dog"})
+            .await;
+        cx.assert_shared_clipboard("fox jumps over\nthe lazy dog\n")
+            .await;
+    }
+
+    #[gpui::test]
+    async fn test_visual_block_mode(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.set_shared_state(indoc! {
+            "The ˇquick brown
+             fox jumps over
+             the lazy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["ctrl-v"]).await;
+        cx.assert_shared_state(indoc! {
+            "The «qˇ»uick brown
+            fox jumps over
+            the lazy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["2", "down"]).await;
+        cx.assert_shared_state(indoc! {
+            "The «qˇ»uick brown
+            fox «jˇ»umps over
+            the «lˇ»azy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["e"]).await;
+        cx.assert_shared_state(indoc! {
+            "The «quicˇ»k brown
+            fox «jumpˇ»s over
+            the «lazyˇ» dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["^"]).await;
+        cx.assert_shared_state(indoc! {
+            "«ˇThe q»uick brown
+            «ˇfox j»umps over
+            «ˇthe l»azy dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["$"]).await;
+        cx.assert_shared_state(indoc! {
+            "The «quick brownˇ»
+            fox «jumps overˇ»
+            the «lazy dogˇ»"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["shift-f", " "]).await;
+        cx.assert_shared_state(indoc! {
+            "The «quickˇ» brown
+            fox «jumpsˇ» over
+            the «lazy ˇ»dog"
+        })
+        .await;
+
+        // toggling through visual mode works as expected
+        cx.simulate_shared_keystrokes(["v"]).await;
+        cx.assert_shared_state(indoc! {
+            "The «quick brown
+            fox jumps over
+            the lazy ˇ»dog"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["ctrl-v"]).await;
+        cx.assert_shared_state(indoc! {
+            "The «quickˇ» brown
+            fox «jumpsˇ» over
+            the «lazy ˇ»dog"
+        })
+        .await;
+
+        cx.set_shared_state(indoc! {
+            "The ˇquick
+             brown
+             fox
+             jumps over the
+
+             lazy dog
+            "
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["ctrl-v", "down", "down"])
+            .await;
+        cx.assert_shared_state(indoc! {
+            "The«ˇ q»uick
+            bro«ˇwn»
+            foxˇ
+            jumps over the
+
+            lazy dog
+            "
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["down"]).await;
+        cx.assert_shared_state(indoc! {
+            "The «qˇ»uick
+            brow«nˇ»
+            fox
+            jump«sˇ» over the
+
+            lazy dog
+            "
+        })
+        .await;
+        cx.simulate_shared_keystroke("left").await;
+        cx.assert_shared_state(indoc! {
+            "The«ˇ q»uick
+            bro«ˇwn»
+            foxˇ
+            jum«ˇps» over the
+
+            lazy dog
+            "
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["s", "o", "escape"]).await;
+        cx.assert_shared_state(indoc! {
+            "Theˇouick
+            broo
+            foxo
+            jumo over the
+
+            lazy dog
+            "
+        })
+        .await;
+
+        //https://github.com/zed-industries/community/issues/1950
+        cx.set_shared_state(indoc! {
+            "Theˇ quick brown
+
+            fox jumps over
+            the lazy dog
+            "
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["l", "ctrl-v", "j", "j"])
+            .await;
+        cx.assert_shared_state(indoc! {
+            "The «qˇ»uick brown
+
+            fox «jˇ»umps over
+            the lazy dog
+            "
+        })
+        .await;
+    }
+
+    #[gpui::test]
+    async fn test_visual_block_issue_2123(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.set_shared_state(indoc! {
+            "The ˇquick brown
+            fox jumps over
+            the lazy dog
+            "
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["ctrl-v", "right", "down"])
+            .await;
+        cx.assert_shared_state(indoc! {
+            "The «quˇ»ick brown
+            fox «juˇ»mps over
+            the lazy dog
+            "
+        })
+        .await;
+    }
+
+    #[gpui::test]
+    async fn test_visual_block_insert(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.set_shared_state(indoc! {
+            "ˇThe quick brown
+            fox jumps over
+            the lazy dog
+            "
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["ctrl-v", "9", "down"]).await;
+        cx.assert_shared_state(indoc! {
+            "«Tˇ»he quick brown
+            «fˇ»ox jumps over
+            «tˇ»he lazy dog
+            ˇ"
+        })
+        .await;
+
+        cx.simulate_shared_keystrokes(["shift-i", "k", "escape"])
+            .await;
+        cx.assert_shared_state(indoc! {
+            "ˇkThe quick brown
+            kfox jumps over
+            kthe lazy dog
+            k"
+        })
+        .await;
+
+        cx.set_shared_state(indoc! {
+            "ˇThe quick brown
+            fox jumps over
+            the lazy dog
+            "
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["ctrl-v", "9", "down"]).await;
+        cx.assert_shared_state(indoc! {
+            "«Tˇ»he quick brown
+            «fˇ»ox jumps over
+            «tˇ»he lazy dog
+            ˇ"
+        })
+        .await;
+        cx.simulate_shared_keystrokes(["c", "k", "escape"]).await;
+        cx.assert_shared_state(indoc! {
+            "ˇkhe quick brown
+            kox jumps over
+            khe lazy dog
+            k"
+        })
+        .await;
+    }
+
+    #[gpui::test]
+    async fn test_visual_object(cx: &mut gpui::TestAppContext) {
+        let mut cx = NeovimBackedTestContext::new(cx).await;
+
+        cx.set_shared_state("hello (in [parˇens] o)").await;
+        cx.simulate_shared_keystrokes(["ctrl-v", "l"]).await;
+        cx.simulate_shared_keystrokes(["a", "]"]).await;
+        cx.assert_shared_state("hello (in «[parens]ˇ» o)").await;
+        assert_eq!(cx.mode(), Mode::Visual);
+        cx.simulate_shared_keystrokes(["i", "("]).await;
+        cx.assert_shared_state("hello («in [parens] oˇ»)").await;
+
+        cx.set_shared_state("hello in a wˇord again.").await;
+        cx.simulate_shared_keystrokes(["ctrl-v", "l", "i", "w"])
+            .await;
+        cx.assert_shared_state("hello in a w«ordˇ» again.").await;
+        assert_eq!(cx.mode(), Mode::VisualBlock);
+        cx.simulate_shared_keystrokes(["o", "a", "s"]).await;
+        cx.assert_shared_state("«ˇhello in a word» again.").await;
+        assert_eq!(cx.mode(), Mode::Visual);
+    }
+
+    #[gpui::test]
+    async fn test_mode_across_command(cx: &mut gpui::TestAppContext) {
+        let mut cx = VimTestContext::new(cx, true).await;
+
+        cx.set_state("aˇbc", Mode::Normal);
+        cx.simulate_keystrokes(["ctrl-v"]);
+        assert_eq!(cx.mode(), Mode::VisualBlock);
+        cx.simulate_keystrokes(["cmd-shift-p", "escape"]);
+        assert_eq!(cx.mode(), Mode::VisualBlock);
+    }
+}