All the easy tests?

Conrad Irwin created

Change summary

crates/vim2/src/insert.rs      |  184 ++---
crates/vim2/src/motion.rs      |  297 ++++----
crates/vim2/src/normal/case.rs |   68 +-
crates/vim2/src/visual.rs      | 1133 ++++++++++++++++++-----------------
4 files changed, 843 insertions(+), 839 deletions(-)

Detailed changes

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/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);
+    }
+}