vim test redux (#11709)

This cleans up the neovim-backed vim tests:
- removed exempted tests (we'll rely on bug reports to find missing edge
cases)
- moved all assertions into non-async fn's so that failures are
reporting on the right file/line
- removed the NeovimBackedBindingTestContext
- renamed a few things to make them clearer
- reduced the number of permutations tested in some cases to reduce
slowest test from 60s to 5s

Release Notes:

- N/A
This commit is contained in:
Conrad Irwin 2024-05-11 12:04:05 -06:00 committed by GitHub
parent 48cba328f2
commit f550f23b97
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
38 changed files with 2311 additions and 6505 deletions

View File

@ -193,32 +193,11 @@ impl EditorTestContext {
self.assertion_cx.context()
}
pub fn simulate_keystroke(&mut self, keystroke_text: &str) -> ContextHandle {
let keystroke_under_test_handle =
self.add_assertion_context(format!("Simulated Keystroke: {:?}", keystroke_text));
// unlike cx.simulate_keystrokes(), this does not run_until_parked
// so you can use it to test detailed timing
pub fn simulate_keystroke(&mut self, keystroke_text: &str) {
let keystroke = Keystroke::parse(keystroke_text).unwrap();
self.cx.dispatch_keystroke(self.window, keystroke);
keystroke_under_test_handle
}
pub fn simulate_keystrokes<const COUNT: usize>(
&mut self,
keystroke_texts: [&str; COUNT],
) -> ContextHandle {
let keystrokes_under_test_handle =
self.add_assertion_context(format!("Simulated Keystrokes: {:?}", keystroke_texts));
for keystroke_text in keystroke_texts.into_iter() {
self.simulate_keystroke(keystroke_text);
}
// it is common for keyboard shortcuts to kick off async actions, so this ensures that they are complete
// before returning.
// NOTE: we don't do this in simulate_keystroke() because a possible cause of bugs is that typing too
// quickly races with async actions.
self.cx.background_executor.run_until_parked();
keystrokes_under_test_handle
}
pub fn run_until_parked(&mut self) {

View File

@ -102,20 +102,16 @@ mod test {
cx.set_shared_state("ˇ").await;
cx.simulate_shared_keystrokes([
"i", "1", "1", "escape", "shift-o", "2", "2", "escape", "shift-g", "o", "3", "3",
"escape",
])
.await;
cx.simulate_shared_keystrokes("i 1 1 escape shift-o 2 2 escape shift-g o 3 3 escape")
.await;
cx.assert_shared_state(indoc! {
cx.shared_state().await.assert_eq(indoc! {
"22
11
3ˇ3"
})
.await;
});
cx.simulate_shared_keystrokes(["g", ";"]).await;
cx.simulate_shared_keystrokes("g ;").await;
// NOTE: this matches nvim when I type it into it
// but in tests, nvim always reports the column as 0...
cx.assert_state(
@ -126,7 +122,7 @@ mod test {
},
Mode::Normal,
);
cx.simulate_shared_keystrokes(["g", ";"]).await;
cx.simulate_shared_keystrokes("g ;").await;
cx.assert_state(
indoc! {
"2ˇ2
@ -135,7 +131,7 @@ mod test {
},
Mode::Normal,
);
cx.simulate_shared_keystrokes(["g", ";"]).await;
cx.simulate_shared_keystrokes("g ;").await;
cx.assert_state(
indoc! {
"22
@ -144,7 +140,7 @@ mod test {
},
Mode::Normal,
);
cx.simulate_shared_keystrokes(["g", ","]).await;
cx.simulate_shared_keystrokes("g ,").await;
cx.assert_state(
indoc! {
"2ˇ2
@ -153,9 +149,8 @@ mod test {
},
Mode::Normal,
);
cx.simulate_shared_keystrokes(["shift-g", "i", "4", "4", "escape"])
.await;
cx.simulate_shared_keystrokes(["g", ";"]).await;
cx.simulate_shared_keystrokes("shift-g i 4 4 escape").await;
cx.simulate_shared_keystrokes("g ;").await;
cx.assert_state(
indoc! {
"22
@ -164,7 +159,7 @@ mod test {
},
Mode::Normal,
);
cx.simulate_shared_keystrokes(["g", ";"]).await;
cx.simulate_shared_keystrokes("g ;").await;
cx.assert_state(
indoc! {
"2ˇ2
@ -182,22 +177,18 @@ mod test {
"one two
three fˇour"})
.await;
cx.simulate_shared_keystrokes(["x", "k", "d", "i", "w", "^", "x"])
.await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes("x k d i w ^ x").await;
cx.shared_state().await.assert_eq(indoc! {
"ˇne•
three fur"})
.await;
cx.simulate_shared_keystrokes(["2", "g", ";"]).await;
cx.assert_shared_state(indoc! {
three fur"});
cx.simulate_shared_keystrokes("2 g ;").await;
cx.shared_state().await.assert_eq(indoc! {
"ne•
three fˇur"})
.await;
cx.simulate_shared_keystrokes(["g", ","]).await;
cx.assert_shared_state(indoc! {
three fˇur"});
cx.simulate_shared_keystrokes("g ,").await;
cx.shared_state().await.assert_eq(indoc! {
"ˇne•
three fur"})
.await;
three fur"});
}
#[gpui::test]
@ -207,13 +198,11 @@ mod test {
"one two
three fˇr"})
.await;
cx.simulate_shared_keystrokes(["i", "o", "escape", "k", "g", "i"])
.await;
cx.simulate_shared_keystrokes(["u", "escape"]).await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes("i o escape k g i").await;
cx.simulate_shared_keystrokes("u escape").await;
cx.shared_state().await.assert_eq(indoc! {
"one two
three foˇur"})
.await;
three foˇur"});
}
#[gpui::test]
@ -223,11 +212,9 @@ mod test {
"one two
three fˇr"})
.await;
cx.simulate_shared_keystrokes(["i", "o", "escape", "k", "`", "."])
.await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes("i o escape k ` .").await;
cx.shared_state().await.assert_eq(indoc! {
"one two
three fˇor"})
.await;
three fˇor"});
}
}

View File

@ -404,15 +404,14 @@ mod test {
c"})
.await;
cx.simulate_shared_keystrokes([":", "j", "enter"]).await;
cx.simulate_shared_keystrokes(": j enter").await;
// hack: our cursor positionining after a join command is wrong
cx.simulate_shared_keystrokes(["^"]).await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes("^").await;
cx.shared_state().await.assert_eq(indoc! {
"ˇa b
c"
})
.await;
});
}
#[gpui::test]
@ -424,12 +423,11 @@ mod test {
b
c"})
.await;
cx.simulate_shared_keystrokes([":", "3", "enter"]).await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes(": 3 enter").await;
cx.shared_state().await.assert_eq(indoc! {"
a
b
ˇc"})
.await;
ˇc"});
}
#[gpui::test]
@ -441,22 +439,17 @@ mod test {
b
c"})
.await;
cx.simulate_shared_keystrokes([":", "%", "s", "/", "b", "/", "d", "enter"])
.await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes(": % s / b / d enter").await;
cx.shared_state().await.assert_eq(indoc! {"
a
ˇd
c"})
c"});
cx.simulate_shared_keystrokes(": % s : . : \\ 0 \\ 0 enter")
.await;
cx.simulate_shared_keystrokes([
":", "%", "s", ":", ".", ":", "\\", "0", "\\", "0", "enter",
])
.await;
cx.assert_shared_state(indoc! {"
cx.shared_state().await.assert_eq(indoc! {"
aa
dd
ˇcc"})
.await;
ˇcc"});
}
#[gpui::test]
@ -469,22 +462,18 @@ mod test {
a
c"})
.await;
cx.simulate_shared_keystrokes([":", "/", "b", "enter"])
.await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes(": / b enter").await;
cx.shared_state().await.assert_eq(indoc! {"
a
ˇb
a
c"})
.await;
cx.simulate_shared_keystrokes([":", "?", "a", "enter"])
.await;
cx.assert_shared_state(indoc! {"
c"});
cx.simulate_shared_keystrokes(": ? a enter").await;
cx.shared_state().await.assert_eq(indoc! {"
ˇa
b
a
c"})
.await;
c"});
}
#[gpui::test]
@ -493,23 +482,23 @@ mod test {
let path = Path::new("/root/dir/file.rs");
let fs = cx.workspace(|workspace, cx| workspace.project().read(cx).fs().clone());
cx.simulate_keystrokes(["i", "@", "escape"]);
cx.simulate_keystrokes([":", "w", "enter"]);
cx.simulate_keystrokes("i @ escape");
cx.simulate_keystrokes(": w enter");
assert_eq!(fs.load(&path).await.unwrap(), "@\n");
fs.as_fake().insert_file(path, b"oops\n".to_vec()).await;
// conflict!
cx.simulate_keystrokes(["i", "@", "escape"]);
cx.simulate_keystrokes([":", "w", "enter"]);
cx.simulate_keystrokes("i @ escape");
cx.simulate_keystrokes(": w enter");
assert!(cx.has_pending_prompt());
// "Cancel"
cx.simulate_prompt_answer(0);
assert_eq!(fs.load(&path).await.unwrap(), "oops\n");
assert!(!cx.has_pending_prompt());
// force overwrite
cx.simulate_keystrokes([":", "w", "!", "enter"]);
cx.simulate_keystrokes(": w ! enter");
assert!(!cx.has_pending_prompt());
assert_eq!(fs.load(&path).await.unwrap(), "@@\n");
}
@ -518,13 +507,13 @@ mod test {
async fn test_command_quit(cx: &mut TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
cx.simulate_keystrokes([":", "n", "e", "w", "enter"]);
cx.simulate_keystrokes(": n e w enter");
cx.workspace(|workspace, cx| assert_eq!(workspace.items(cx).count(), 2));
cx.simulate_keystrokes([":", "q", "enter"]);
cx.simulate_keystrokes(": q enter");
cx.workspace(|workspace, cx| assert_eq!(workspace.items(cx).count(), 1));
cx.simulate_keystrokes([":", "n", "e", "w", "enter"]);
cx.simulate_keystrokes(": n e w enter");
cx.workspace(|workspace, cx| assert_eq!(workspace.items(cx).count(), 2));
cx.simulate_keystrokes([":", "q", "a", "enter"]);
cx.simulate_keystrokes(": q a enter");
cx.workspace(|workspace, cx| assert_eq!(workspace.items(cx).count(), 0));
}
}

View File

@ -46,11 +46,11 @@ mod test {
#[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");
cx.simulate_keystrokes("i");
assert_eq!(cx.mode(), Mode::Insert);
cx.simulate_keystrokes(["T", "e", "s", "t"]);
cx.simulate_keystrokes("T e s t");
cx.assert_editor_state("Testˇ");
cx.simulate_keystroke("escape");
cx.simulate_keystrokes("escape");
assert_eq!(cx.mode(), Mode::Normal);
cx.assert_editor_state("Tesˇt");
}
@ -60,38 +60,32 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.set_shared_state("ˇhello\n").await;
cx.simulate_shared_keystrokes(["5", "i", "-", "escape"])
.await;
cx.simulate_shared_keystrokes("5 i - escape").await;
cx.run_until_parked();
cx.assert_shared_state("----ˇ-hello\n").await;
cx.shared_state().await.assert_eq("----ˇ-hello\n");
cx.set_shared_state("ˇhello\n").await;
cx.simulate_shared_keystrokes(["5", "a", "-", "escape"])
.await;
cx.simulate_shared_keystrokes("5 a - escape").await;
cx.run_until_parked();
cx.assert_shared_state("h----ˇ-ello\n").await;
cx.shared_state().await.assert_eq("h----ˇ-ello\n");
cx.simulate_shared_keystrokes(["4", "shift-i", "-", "escape"])
.await;
cx.simulate_shared_keystrokes("4 shift-i - escape").await;
cx.run_until_parked();
cx.assert_shared_state("---ˇ-h-----ello\n").await;
cx.shared_state().await.assert_eq("---ˇ-h-----ello\n");
cx.simulate_shared_keystrokes(["3", "shift-a", "-", "escape"])
.await;
cx.simulate_shared_keystrokes("3 shift-a - escape").await;
cx.run_until_parked();
cx.assert_shared_state("----h-----ello--ˇ-\n").await;
cx.shared_state().await.assert_eq("----h-----ello--ˇ-\n");
cx.set_shared_state("ˇhello\n").await;
cx.simulate_shared_keystrokes(["3", "o", "o", "i", "escape"])
.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.shared_state().await.assert_eq("hello\noi\noi\noˇi\n");
cx.set_shared_state("ˇhello\n").await;
cx.simulate_shared_keystrokes(["3", "shift-o", "o", "i", "escape"])
.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;
cx.shared_state().await.assert_eq("oi\noi\noˇi\nhello\n");
}
#[gpui::test]
@ -99,27 +93,29 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.set_shared_state("ˇhello\n").await;
cx.simulate_shared_keystrokes(["3", "i", "-", "escape"])
.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.shared_state().await.assert_eq("--ˇ-hello\n");
cx.simulate_shared_keystrokes(".").await;
cx.run_until_parked();
cx.assert_shared_state("----ˇ--hello\n").await;
cx.simulate_shared_keystrokes(["2", "."]).await;
cx.shared_state().await.assert_eq("----ˇ--hello\n");
cx.simulate_shared_keystrokes("2 .").await;
cx.run_until_parked();
cx.assert_shared_state("-----ˇ---hello\n").await;
cx.shared_state().await.assert_eq("-----ˇ---hello\n");
cx.set_shared_state("ˇhello\n").await;
cx.simulate_shared_keystrokes(["2", "o", "k", "k", "escape"])
.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.shared_state().await.assert_eq("hello\nkk\nkˇk\n");
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.shared_state()
.await
.assert_eq("hello\nkk\nkk\nkk\nkˇk\n");
cx.simulate_shared_keystrokes("1 .").await;
cx.run_until_parked();
cx.assert_shared_state("hello\nkk\nkk\nkk\nkk\nkˇk\n").await;
cx.shared_state()
.await
.assert_eq("hello\nkk\nkk\nkk\nkk\nkˇk\n");
}
}

View File

@ -1779,8 +1779,8 @@ mod test {
// goes down once
cx.set_shared_state(initial_state).await;
cx.simulate_shared_keystrokes(["}"]).await;
cx.assert_shared_state(indoc! {r"abc
cx.simulate_shared_keystrokes("}").await;
cx.shared_state().await.assert_eq(indoc! {r"abc
def
ˇ
paragraph
@ -1789,16 +1789,15 @@ mod test {
third and
final"})
.await;
final"});
// goes up once
cx.simulate_shared_keystrokes(["{"]).await;
cx.assert_shared_state(initial_state).await;
cx.simulate_shared_keystrokes("{").await;
cx.shared_state().await.assert_eq(initial_state);
// goes down twice
cx.simulate_shared_keystrokes(["2", "}"]).await;
cx.assert_shared_state(indoc! {r"abc
cx.simulate_shared_keystrokes("2 }").await;
cx.shared_state().await.assert_eq(indoc! {r"abc
def
paragraph
@ -1807,12 +1806,11 @@ mod test {
third and
final"})
.await;
final"});
// goes down over multiple blanks
cx.simulate_shared_keystrokes(["}"]).await;
cx.assert_shared_state(indoc! {r"abc
cx.simulate_shared_keystrokes("}").await;
cx.shared_state().await.assert_eq(indoc! {r"abc
def
paragraph
@ -1821,12 +1819,11 @@ mod test {
third and
finaˇl"})
.await;
finaˇl"});
// goes up twice
cx.simulate_shared_keystrokes(["2", "{"]).await;
cx.assert_shared_state(indoc! {r"abc
cx.simulate_shared_keystrokes("2 {").await;
cx.shared_state().await.assert_eq(indoc! {r"abc
def
ˇ
paragraph
@ -1835,8 +1832,7 @@ mod test {
third and
final"})
.await
final"});
}
#[gpui::test]
@ -1847,39 +1843,41 @@ mod test {
do(something(with<Types>.and_arrays[0, 2]))
}"})
.await;
cx.simulate_shared_keystrokes(["%"]).await;
cx.assert_shared_state(indoc! {r"func (a stringˇ) {
cx.simulate_shared_keystrokes("%").await;
cx.shared_state()
.await
.assert_eq(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) {
cx.simulate_shared_keystrokes("%").await;
cx.shared_state()
.await
.assert_eq(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;
cx.simulate_shared_keystrokes("%").await;
cx.shared_state().await.assert_eq("{()ˇ}");
cx.simulate_shared_keystrokes("%").await;
cx.shared_state().await.assert_eq("ˇ{()}");
// 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;
cx.simulate_shared_keystrokes("%").await;
cx.shared_state().await.assert_eq("{\n {()ˇ}\n}");
// 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;
cx.simulate_shared_keystrokes("%").await;
cx.shared_state().await.assert_eq("func boop(ˇ) {\n}");
}
#[gpui::test]
@ -1888,33 +1886,33 @@ mod test {
// f and F
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-f", "e"]).await;
cx.assert_shared_state("one two threˇe four").await;
cx.simulate_shared_keystrokes(["2", ";"]).await;
cx.assert_shared_state("onˇe two three four").await;
cx.simulate_shared_keystrokes([","]).await;
cx.assert_shared_state("one two thrˇee four").await;
cx.simulate_shared_keystrokes("f o").await;
cx.shared_state().await.assert_eq("one twˇo three four");
cx.simulate_shared_keystrokes(",").await;
cx.shared_state().await.assert_eq("ˇone two three four");
cx.simulate_shared_keystrokes("2 ;").await;
cx.shared_state().await.assert_eq("one two three fˇour");
cx.simulate_shared_keystrokes("shift-f e").await;
cx.shared_state().await.assert_eq("one two threˇe four");
cx.simulate_shared_keystrokes("2 ;").await;
cx.shared_state().await.assert_eq("onˇe two three four");
cx.simulate_shared_keystrokes(",").await;
cx.shared_state().await.assert_eq("one two thrˇee four");
// t and T
cx.set_shared_state("ˇone two three four").await;
cx.simulate_shared_keystrokes(["t", "o"]).await;
cx.assert_shared_state("one tˇwo three four").await;
cx.simulate_shared_keystrokes([","]).await;
cx.assert_shared_state("oˇne two three four").await;
cx.simulate_shared_keystrokes(["2", ";"]).await;
cx.assert_shared_state("one two three ˇfour").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;
cx.simulate_shared_keystrokes("t o").await;
cx.shared_state().await.assert_eq("one tˇwo three four");
cx.simulate_shared_keystrokes(",").await;
cx.shared_state().await.assert_eq("oˇne two three four");
cx.simulate_shared_keystrokes("2 ;").await;
cx.shared_state().await.assert_eq("one two three ˇfour");
cx.simulate_shared_keystrokes("shift-t e").await;
cx.shared_state().await.assert_eq("one two threeˇ four");
cx.simulate_shared_keystrokes("3 ;").await;
cx.shared_state().await.assert_eq("oneˇ two three four");
cx.simulate_shared_keystrokes(",").await;
cx.shared_state().await.assert_eq("one two thˇree four");
}
#[gpui::test]
@ -1922,26 +1920,26 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
let initial_state = indoc! {r"something(ˇfoo)"};
cx.set_shared_state(initial_state).await;
cx.simulate_shared_keystrokes(["}"]).await;
cx.assert_shared_state(indoc! {r"something(fooˇ)"}).await;
cx.simulate_shared_keystrokes("}").await;
cx.shared_state().await.assert_eq("something(fooˇ)");
}
#[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;
cx.simulate_shared_keystrokes("enter").await;
cx.shared_state().await.assert_eq("one\n ˇtwo\nthree");
}
#[gpui::test]
async fn test_end_of_line_downward(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.set_shared_state("ˇ one \n two \nthree").await;
cx.simulate_shared_keystrokes(["g", "_"]).await;
cx.assert_shared_state(" onˇe \n two \nthree").await;
cx.simulate_shared_keystrokes(["2", "g", "_"]).await;
cx.assert_shared_state(" one \n twˇo \nthree").await;
cx.simulate_shared_keystrokes("g _").await;
cx.shared_state().await.assert_eq(" onˇe \n two \nthree");
cx.simulate_shared_keystrokes("2 g _").await;
cx.shared_state().await.assert_eq(" one \n twˇo \nthree");
}
#[gpui::test]
@ -1955,14 +1953,13 @@ mod test {
final"};
cx.set_shared_state(initial_state).await;
cx.simulate_shared_keystrokes(["shift-h"]).await;
cx.assert_shared_state(indoc! {r"abˇc
cx.simulate_shared_keystrokes("shift-h").await;
cx.shared_state().await.assert_eq(indoc! {r"abˇc
def
paragraph
the second
third and
final"})
.await;
final"});
// clip point
cx.set_shared_state(indoc! {r"
@ -1971,13 +1968,12 @@ mod test {
7 8 ˇ9
"})
.await;
cx.simulate_shared_keystrokes(["shift-h"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("shift-h").await;
cx.shared_state().await.assert_eq(indoc! {"
1 2 ˇ3
4 5 6
7 8 9
"})
.await;
"});
cx.set_shared_state(indoc! {r"
1 2 3
@ -1985,25 +1981,23 @@ mod test {
ˇ7 8 9
"})
.await;
cx.simulate_shared_keystrokes(["shift-h"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("shift-h").await;
cx.shared_state().await.assert_eq(indoc! {"
ˇ1 2 3
4 5 6
7 8 9
"})
.await;
"});
cx.set_shared_state(indoc! {r"
1 2 3
4 5 ˇ6
7 8 9"})
.await;
cx.simulate_shared_keystrokes(["9", "shift-h"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("9 shift-h").await;
cx.shared_state().await.assert_eq(indoc! {"
1 2 3
4 5 6
7 8 ˇ9"})
.await;
7 8 ˇ9"});
}
#[gpui::test]
@ -2017,14 +2011,13 @@ mod test {
final"};
cx.set_shared_state(initial_state).await;
cx.simulate_shared_keystrokes(["shift-m"]).await;
cx.assert_shared_state(indoc! {r"abc
cx.simulate_shared_keystrokes("shift-m").await;
cx.shared_state().await.assert_eq(indoc! {r"abc
def
paˇragraph
the second
third and
final"})
.await;
final"});
cx.set_shared_state(indoc! {r"
1 2 3
@ -2032,65 +2025,60 @@ mod test {
7 8 ˇ9
"})
.await;
cx.simulate_shared_keystrokes(["shift-m"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("shift-m").await;
cx.shared_state().await.assert_eq(indoc! {"
1 2 3
4 5 ˇ6
7 8 9
"})
.await;
"});
cx.set_shared_state(indoc! {r"
1 2 3
4 5 6
ˇ7 8 9
"})
.await;
cx.simulate_shared_keystrokes(["shift-m"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("shift-m").await;
cx.shared_state().await.assert_eq(indoc! {"
1 2 3
ˇ4 5 6
7 8 9
"})
.await;
"});
cx.set_shared_state(indoc! {r"
ˇ1 2 3
4 5 6
7 8 9
"})
.await;
cx.simulate_shared_keystrokes(["shift-m"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("shift-m").await;
cx.shared_state().await.assert_eq(indoc! {"
1 2 3
ˇ4 5 6
7 8 9
"})
.await;
"});
cx.set_shared_state(indoc! {r"
1 2 3
ˇ4 5 6
7 8 9
"})
.await;
cx.simulate_shared_keystrokes(["shift-m"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("shift-m").await;
cx.shared_state().await.assert_eq(indoc! {"
1 2 3
ˇ4 5 6
7 8 9
"})
.await;
"});
cx.set_shared_state(indoc! {r"
1 2 3
4 5 ˇ6
7 8 9
"})
.await;
cx.simulate_shared_keystrokes(["shift-m"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("shift-m").await;
cx.shared_state().await.assert_eq(indoc! {"
1 2 3
4 5 ˇ6
7 8 9
"})
.await;
"});
}
#[gpui::test]
@ -2104,14 +2092,13 @@ mod test {
final"};
cx.set_shared_state(initial_state).await;
cx.simulate_shared_keystrokes(["shift-l"]).await;
cx.assert_shared_state(indoc! {r"abc
cx.simulate_shared_keystrokes("shift-l").await;
cx.shared_state().await.assert_eq(indoc! {r"abc
def
paragraph
the second
third and
fiˇnal"})
.await;
fiˇnal"});
cx.set_shared_state(indoc! {r"
1 2 3
@ -2119,13 +2106,12 @@ mod test {
7 8 9
"})
.await;
cx.simulate_shared_keystrokes(["shift-l"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("shift-l").await;
cx.shared_state().await.assert_eq(indoc! {"
1 2 3
4 5 6
7 8 9
ˇ"})
.await;
ˇ"});
cx.set_shared_state(indoc! {r"
1 2 3
@ -2133,13 +2119,12 @@ mod test {
7 8 9
"})
.await;
cx.simulate_shared_keystrokes(["shift-l"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("shift-l").await;
cx.shared_state().await.assert_eq(indoc! {"
1 2 3
4 5 6
7 8 9
ˇ"})
.await;
ˇ"});
cx.set_shared_state(indoc! {r"
1 2 ˇ3
@ -2147,13 +2132,12 @@ mod test {
7 8 9
"})
.await;
cx.simulate_shared_keystrokes(["shift-l"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("shift-l").await;
cx.shared_state().await.assert_eq(indoc! {"
1 2 3
4 5 6
7 8 9
ˇ"})
.await;
ˇ"});
cx.set_shared_state(indoc! {r"
ˇ1 2 3
@ -2161,13 +2145,12 @@ mod test {
7 8 9
"})
.await;
cx.simulate_shared_keystrokes(["shift-l"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("shift-l").await;
cx.shared_state().await.assert_eq(indoc! {"
1 2 3
4 5 6
7 8 9
ˇ"})
.await;
ˇ"});
cx.set_shared_state(indoc! {r"
1 2 3
@ -2175,13 +2158,12 @@ mod test {
7 8 9
"})
.await;
cx.simulate_shared_keystrokes(["9", "shift-l"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("9 shift-l").await;
cx.shared_state().await.assert_eq(indoc! {"
1 2 ˇ3
4 5 6
7 8 9
"})
.await;
"});
}
#[gpui::test]
@ -2191,11 +2173,10 @@ mod test {
456 5ˇ67 678
"})
.await;
cx.simulate_shared_keystrokes(["g", "e"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("g e").await;
cx.shared_state().await.assert_eq(indoc! {"
45ˇ6 567 678
"})
.await;
"});
// Test times
cx.set_shared_state(indoc! {r"
@ -2203,12 +2184,11 @@ mod test {
456 5ˇ67 678
"})
.await;
cx.simulate_shared_keystrokes(["4", "g", "e"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("4 g e").await;
cx.shared_state().await.assert_eq(indoc! {"
12ˇ3 234 345
456 567 678
"})
.await;
"});
// With punctuation
cx.set_shared_state(indoc! {r"
@ -2217,13 +2197,12 @@ mod test {
789 890 901
"})
.await;
cx.simulate_shared_keystrokes(["g", "e"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("g e").await;
cx.shared_state().await.assert_eq(indoc! {"
123 234 345
4;5.ˇ6 567 678
789 890 901
"})
.await;
"});
// With punctuation and count
cx.set_shared_state(indoc! {r"
@ -2232,13 +2211,12 @@ mod test {
789 890 901
"})
.await;
cx.simulate_shared_keystrokes(["5", "g", "e"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("5 g e").await;
cx.shared_state().await.assert_eq(indoc! {"
123 234 345
ˇ4;5.6 567 678
789 890 901
"})
.await;
"});
// newlines
cx.set_shared_state(indoc! {r"
@ -2247,20 +2225,18 @@ mod test {
78ˇ9 890 901
"})
.await;
cx.simulate_shared_keystrokes(["g", "e"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("g e").await;
cx.shared_state().await.assert_eq(indoc! {"
123 234 345
ˇ
789 890 901
"})
.await;
cx.simulate_shared_keystrokes(["g", "e"]).await;
cx.assert_shared_state(indoc! {r"
"});
cx.simulate_shared_keystrokes("g e").await;
cx.shared_state().await.assert_eq(indoc! {"
123 234 34ˇ5
789 890 901
"})
.await;
"});
// With punctuation
cx.set_shared_state(indoc! {r"
@ -2269,13 +2245,12 @@ mod test {
789 890 901
"})
.await;
cx.simulate_shared_keystrokes(["g", "shift-e"]).await;
cx.assert_shared_state(indoc! {r"
cx.simulate_shared_keystrokes("g shift-e").await;
cx.shared_state().await.assert_eq(indoc! {"
123 234 34ˇ5
4;5.6 567 678
789 890 901
"})
.await;
"});
}
#[gpui::test]
@ -2288,12 +2263,11 @@ mod test {
}
"})
.await;
cx.simulate_shared_keystrokes(["v", "$", "%"]).await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("v $ %").await;
cx.shared_state().await.assert_eq(indoc! {"
fn a«() {
return
}ˇ»
"})
.await;
"});
}
}

View File

@ -443,24 +443,30 @@ mod test {
#[gpui::test]
async fn test_h(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["h"]);
cx.assert_all(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate_at_each_offset(
"h",
indoc! {"
ˇThe qˇuick
ˇbrown"
})
.await;
},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_backspace(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx)
.await
.binding(["backspace"]);
cx.assert_all(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate_at_each_offset(
"backspace",
indoc! {"
ˇThe qˇuick
ˇbrown"
})
.await;
},
)
.await
.assert_matches();
}
#[gpui::test]
@ -468,320 +474,426 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.set_shared_state(indoc! {"
aaˇaa
😃😃"
})
.await;
cx.simulate_shared_keystrokes(["j"]).await;
cx.assert_shared_state(indoc! {"
aaaa
😃ˇ😃"
aaˇaa
😃😃"
})
.await;
cx.simulate_shared_keystrokes("j").await;
cx.shared_state().await.assert_eq(indoc! {"
aaaa
😃ˇ😃"
});
for marked_position in cx.each_marked_position(indoc! {"
ˇThe qˇuick broˇwn
ˇfox jumps"
}) {
cx.assert_neovim_compatible(&marked_position, ["j"]).await;
}
cx.simulate_at_each_offset(
"j",
indoc! {"
ˇThe qˇuick broˇwn
ˇfox jumps"
},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_enter(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["enter"]);
cx.assert_all(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate_at_each_offset(
"enter",
indoc! {"
ˇThe qˇuick broˇwn
ˇfox jumps"
})
.await;
},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_k(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["k"]);
cx.assert_all(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate_at_each_offset(
"k",
indoc! {"
ˇThe qˇuick
ˇbrown fˇox jumˇps"
})
.await;
},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_l(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["l"]);
cx.assert_all(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate_at_each_offset(
"l",
indoc! {"
ˇThe qˇuicˇk
ˇbrowˇn"})
.await;
ˇbrowˇn"},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_jump_to_line_boundaries(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.assert_binding_matches_all(
["$"],
cx.simulate_at_each_offset(
"$",
indoc! {"
ˇThe qˇuicˇk
ˇbrowˇn"},
)
.await;
cx.assert_binding_matches_all(
["0"],
.await
.assert_matches();
cx.simulate_at_each_offset(
"0",
indoc! {"
ˇThe qˇuicˇk
ˇbrowˇn"},
)
.await;
.await
.assert_matches();
}
#[gpui::test]
async fn test_jump_to_end(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["shift-g"]);
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.assert_all(indoc! {"
cx.simulate_at_each_offset(
"shift-g",
indoc! {"
The ˇquick
brown fox jumps
overˇ the lazy doˇg"})
.await;
cx.assert(indoc! {"
overˇ the lazy doˇg"},
)
.await
.assert_matches();
cx.simulate(
"shift-g",
indoc! {"
The quiˇck
brown"})
.await;
cx.assert(indoc! {"
brown"},
)
.await
.assert_matches();
cx.simulate(
"shift-g",
indoc! {"
The quiˇck
"})
.await;
"},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_w(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["w"]);
cx.assert_all(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate_at_each_offset(
"w",
indoc! {"
The ˇquickˇ-ˇbrown
ˇ
ˇ
ˇfox_jumps ˇover
ˇthˇe"})
.await;
let mut cx = cx.binding(["shift-w"]);
cx.assert_all(indoc! {"
ˇthˇe"},
)
.await
.assert_matches();
cx.simulate_at_each_offset(
"shift-w",
indoc! {"
The ˇquickˇ-ˇbrown
ˇ
ˇ
ˇfox_jumps ˇover
ˇthˇe"})
.await;
ˇthˇe"},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_end_of_word(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["e"]);
cx.assert_all(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate_at_each_offset(
"e",
indoc! {"
Thˇe quicˇkˇ-browˇn
fox_jumpˇs oveˇr
thˇe"})
.await;
let mut cx = cx.binding(["shift-e"]);
cx.assert_all(indoc! {"
thˇe"},
)
.await
.assert_matches();
cx.simulate_at_each_offset(
"shift-e",
indoc! {"
Thˇe quicˇkˇ-browˇn
fox_jumpˇs oveˇr
thˇe"})
.await;
thˇe"},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_b(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["b"]);
cx.assert_all(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate_at_each_offset(
"b",
indoc! {"
ˇThe ˇquickˇ-ˇbrown
ˇ
ˇ
ˇfox_jumps ˇover
ˇthe"})
.await;
let mut cx = cx.binding(["shift-b"]);
cx.assert_all(indoc! {"
ˇthe"},
)
.await
.assert_matches();
cx.simulate_at_each_offset(
"shift-b",
indoc! {"
ˇThe ˇquickˇ-ˇbrown
ˇ
ˇ
ˇfox_jumps ˇover
ˇthe"})
.await;
ˇthe"},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_gg(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.assert_binding_matches_all(
["g", "g"],
cx.simulate_at_each_offset(
"g g",
indoc! {"
The qˇuick
brown fox jumps
over ˇthe laˇzy dog"},
)
.await;
cx.assert_binding_matches(
["g", "g"],
.await
.assert_matches();
cx.simulate(
"g g",
indoc! {"
brown fox jumps
over the laˇzy dog"},
)
.await;
cx.assert_binding_matches(
["2", "g", "g"],
.await
.assert_matches();
cx.simulate(
"2 g g",
indoc! {"
ˇ
brown fox jumps
over the lazydog"},
)
.await;
.await
.assert_matches();
}
#[gpui::test]
async fn test_end_of_document(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.assert_binding_matches_all(
["shift-g"],
cx.simulate_at_each_offset(
"shift-g",
indoc! {"
The qˇuick
brown fox jumps
over ˇthe laˇzy dog"},
)
.await;
cx.assert_binding_matches(
["shift-g"],
.await
.assert_matches();
cx.simulate(
"shift-g",
indoc! {"
brown fox jumps
over the laˇzy dog"},
)
.await;
cx.assert_binding_matches(
["2", "shift-g"],
.await
.assert_matches();
cx.simulate(
"2 shift-g",
indoc! {"
ˇ
brown fox jumps
over the lazydog"},
)
.await;
.await
.assert_matches();
}
#[gpui::test]
async fn test_a(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["a"]);
cx.assert_all("The qˇuicˇk").await;
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate_at_each_offset("a", "The qˇuicˇk")
.await
.assert_matches();
}
#[gpui::test]
async fn test_insert_end_of_line(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["shift-a"]);
cx.assert_all(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate_at_each_offset(
"shift-a",
indoc! {"
ˇ
The qˇuick
brown ˇfox "})
.await;
brown ˇfox "},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_jump_to_first_non_whitespace(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["^"]);
cx.assert("The qˇuick").await;
cx.assert(" The qˇuick").await;
cx.assert("ˇ").await;
cx.assert(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate("^", "The qˇuick").await.assert_matches();
cx.simulate("^", " The qˇuick").await.assert_matches();
cx.simulate("^", "ˇ").await.assert_matches();
cx.simulate(
"^",
indoc! {"
The qˇuick
brown fox"})
.await;
cx.assert(indoc! {"
brown fox"},
)
.await
.assert_matches();
cx.simulate(
"^",
indoc! {"
ˇ
The quick"})
.await;
The quick"},
)
.await
.assert_matches();
// Indoc disallows trailing whitespace.
cx.assert(" ˇ \nThe quick").await;
cx.simulate("^", " ˇ \nThe quick").await.assert_matches();
}
#[gpui::test]
async fn test_insert_first_non_whitespace(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["shift-i"]);
cx.assert("The qˇuick").await;
cx.assert(" The qˇuick").await;
cx.assert("ˇ").await;
cx.assert(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate("shift-i", "The qˇuick").await.assert_matches();
cx.simulate("shift-i", " The qˇuick").await.assert_matches();
cx.simulate("shift-i", "ˇ").await.assert_matches();
cx.simulate(
"shift-i",
indoc! {"
The qˇuick
brown fox"})
.await;
cx.assert(indoc! {"
brown fox"},
)
.await
.assert_matches();
cx.simulate(
"shift-i",
indoc! {"
ˇ
The quick"})
.await;
The quick"},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_delete_to_end_of_line(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["shift-d"]);
cx.assert(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate(
"shift-d",
indoc! {"
The qˇuick
brown fox"})
.await;
cx.assert(indoc! {"
brown fox"},
)
.await
.assert_matches();
cx.simulate(
"shift-d",
indoc! {"
The quick
ˇ
brown fox"})
.await;
brown fox"},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_x(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["x"]);
cx.assert_all("ˇTeˇsˇt").await;
cx.assert(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate_at_each_offset("x", "ˇTeˇsˇt")
.await
.assert_matches();
cx.simulate(
"x",
indoc! {"
Tesˇt
test"})
.await;
test"},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_delete_left(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["shift-x"]);
cx.assert_all("ˇTˇeˇsˇt").await;
cx.assert(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate_at_each_offset("shift-x", "ˇTˇeˇsˇt")
.await
.assert_matches();
cx.simulate(
"shift-x",
indoc! {"
Test
ˇtest"})
.await;
ˇtest"},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_o(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["o"]);
cx.assert("ˇ").await;
cx.assert("The ˇquick").await;
cx.assert_all(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate("o", "ˇ").await.assert_matches();
cx.simulate("o", "The ˇquick").await.assert_matches();
cx.simulate_at_each_offset(
"o",
indoc! {"
The qˇuick
brown ˇfox
jumps ˇover"})
.await;
cx.assert(indoc! {"
jumps ˇover"},
)
.await
.assert_matches();
cx.simulate(
"o",
indoc! {"
The quick
ˇ
brown fox"})
.await;
brown fox"},
)
.await
.assert_matches();
cx.assert_manual(
cx.assert_binding(
"o",
indoc! {"
fn test() {
println!(ˇ);
@ -795,7 +907,8 @@ mod test {
Mode::Insert,
);
cx.assert_manual(
cx.assert_binding(
"o",
indoc! {"
fn test(ˇ) {
println!();
@ -812,23 +925,31 @@ mod test {
#[gpui::test]
async fn test_insert_line_above(cx: &mut gpui::TestAppContext) {
let cx = NeovimBackedTestContext::new(cx).await;
let mut cx = cx.binding(["shift-o"]);
cx.assert("ˇ").await;
cx.assert("The ˇquick").await;
cx.assert_all(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate("shift-o", "ˇ").await.assert_matches();
cx.simulate("shift-o", "The ˇquick").await.assert_matches();
cx.simulate_at_each_offset(
"shift-o",
indoc! {"
The qˇuick
brown ˇfox
jumps ˇover"})
.await;
cx.assert(indoc! {"
jumps ˇover"},
)
.await
.assert_matches();
cx.simulate(
"shift-o",
indoc! {"
The quick
ˇ
brown fox"})
.await;
brown fox"},
)
.await
.assert_matches();
// Our indentation is smarter than vims. So we don't match here
cx.assert_manual(
cx.assert_binding(
"shift-o",
indoc! {"
fn test() {
println!(ˇ);
@ -841,7 +962,8 @@ mod test {
}"},
Mode::Insert,
);
cx.assert_manual(
cx.assert_binding(
"shift-o",
indoc! {"
fn test(ˇ) {
println!();
@ -859,40 +981,51 @@ mod test {
#[gpui::test]
async fn test_dd(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.assert_neovim_compatible("ˇ", ["d", "d"]).await;
cx.assert_neovim_compatible("The ˇquick", ["d", "d"]).await;
for marked_text in cx.each_marked_position(indoc! {"
cx.simulate("d d", "ˇ").await.assert_matches();
cx.simulate("d d", "The ˇquick").await.assert_matches();
cx.simulate_at_each_offset(
"d d",
indoc! {"
The qˇuick
brown ˇfox
jumps ˇover"})
{
cx.assert_neovim_compatible(&marked_text, ["d", "d"]).await;
}
cx.assert_neovim_compatible(
jumps ˇover"},
)
.await
.assert_matches();
cx.simulate(
"d d",
indoc! {"
The quick
ˇ
brown fox"},
["d", "d"],
)
.await;
.await
.assert_matches();
}
#[gpui::test]
async fn test_cc(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["c", "c"]);
cx.assert("ˇ").await;
cx.assert("The ˇquick").await;
cx.assert_all(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate("c c", "ˇ").await.assert_matches();
cx.simulate("c c", "The ˇquick").await.assert_matches();
cx.simulate_at_each_offset(
"c c",
indoc! {"
The quˇick
brown ˇfox
jumps ˇover"})
.await;
cx.assert(indoc! {"
jumps ˇover"},
)
.await
.assert_matches();
cx.simulate(
"c c",
indoc! {"
The quick
ˇ
brown fox"})
.await;
brown fox"},
)
.await
.assert_matches();
}
#[gpui::test]
@ -900,8 +1033,8 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
for count in 1..=5 {
cx.assert_binding_matches_all(
[&count.to_string(), "w"],
cx.simulate_at_each_offset(
&format!("{count} w"),
indoc! {"
ˇThe quˇickˇ browˇn
ˇ
@ -909,14 +1042,17 @@ mod test {
ˇthe lazy dog
"},
)
.await;
.await
.assert_matches();
}
}
#[gpui::test]
async fn test_h_through_unicode(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["h"]);
cx.assert_all("Testˇ├ˇ──ˇ┐ˇTest").await;
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate_at_each_offset("h", "Testˇ├ˇ──ˇ┐ˇTest")
.await
.assert_matches();
}
#[gpui::test]
@ -931,11 +1067,13 @@ mod test {
ˇb
"};
cx.assert_binding_matches_all([&count.to_string(), "f", "b"], test_case)
.await;
cx.simulate_at_each_offset(&format!("{count} f b"), test_case)
.await
.assert_matches();
cx.assert_binding_matches_all([&count.to_string(), "t", "b"], test_case)
.await;
cx.simulate_at_each_offset(&format!("{count} t b"), test_case)
.await
.assert_matches();
}
}
@ -951,11 +1089,13 @@ mod test {
};
for count in 1..=3 {
cx.assert_binding_matches_all([&count.to_string(), "shift-f", "b"], test_case)
.await;
cx.simulate_at_each_offset(&format!("{count} shift-f b"), test_case)
.await
.assert_matches();
cx.assert_binding_matches_all([&count.to_string(), "shift-t", "b"], test_case)
.await;
cx.simulate_at_each_offset(&format!("{count} shift-t b"), test_case)
.await
.assert_matches();
}
}
@ -969,7 +1109,7 @@ mod test {
});
cx.assert_binding(
["f", "l"],
"f l",
indoc! {"
ˇfunction print() {
console.log('ok')
@ -985,7 +1125,7 @@ mod test {
);
cx.assert_binding(
["t", "l"],
"t l",
indoc! {"
ˇfunction print() {
console.log('ok')
@ -1011,7 +1151,7 @@ mod test {
});
cx.assert_binding(
["shift-f", "p"],
"shift-f p",
indoc! {"
function print() {
console.ˇlog('ok')
@ -1027,7 +1167,7 @@ mod test {
);
cx.assert_binding(
["shift-t", "p"],
"shift-t p",
indoc! {"
function print() {
console.ˇlog('ok')
@ -1053,7 +1193,7 @@ mod test {
});
cx.assert_binding(
["f", "p"],
"f p",
indoc! {"ˇfmt.Println(\"Hello, World!\")"},
Mode::Normal,
indoc! {"fmt.ˇPrintln(\"Hello, World!\")"},
@ -1061,7 +1201,7 @@ mod test {
);
cx.assert_binding(
["shift-f", "p"],
"shift-f p",
indoc! {"fmt.Printlnˇ(\"Hello, World!\")"},
Mode::Normal,
indoc! {"fmt.ˇPrintln(\"Hello, World!\")"},
@ -1069,7 +1209,7 @@ mod test {
);
cx.assert_binding(
["t", "p"],
"t p",
indoc! {"ˇfmt.Println(\"Hello, World!\")"},
Mode::Normal,
indoc! {"fmtˇ.Println(\"Hello, World!\")"},
@ -1077,7 +1217,7 @@ mod test {
);
cx.assert_binding(
["shift-t", "p"],
"shift-t p",
indoc! {"fmt.Printlnˇ(\"Hello, World!\")"},
Mode::Normal,
indoc! {"fmt.Pˇrintln(\"Hello, World!\")"},
@ -1087,11 +1227,16 @@ mod test {
#[gpui::test]
async fn test_percent(cx: &mut TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["%"]);
cx.assert_all("ˇconsole.logˇ(ˇvaˇrˇ)ˇ;").await;
cx.assert_all("ˇconsole.logˇ(ˇ'var', ˇ[ˇ1, ˇ2, 3ˇ]ˇ)ˇ;")
.await;
cx.assert_all("let result = curried_funˇ(ˇ)ˇ(ˇ)ˇ;").await;
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate_at_each_offset("%", "ˇconsole.logˇ(ˇvaˇrˇ)ˇ;")
.await
.assert_matches();
cx.simulate_at_each_offset("%", "ˇconsole.logˇ(ˇ'var', ˇ[ˇ1, ˇ2, 3ˇ]ˇ)ˇ;")
.await
.assert_matches();
cx.simulate_at_each_offset("%", "let result = curried_funˇ(ˇ)ˇ(ˇ)ˇ;")
.await
.assert_matches();
}
#[gpui::test]
@ -1100,16 +1245,16 @@ mod test {
// goes to current line end
cx.set_shared_state(indoc! {"ˇaa\nbb\ncc"}).await;
cx.simulate_shared_keystrokes(["$"]).await;
cx.assert_shared_state(indoc! {"aˇa\nbb\ncc"}).await;
cx.simulate_shared_keystrokes("$").await;
cx.shared_state().await.assert_eq("aˇa\nbb\ncc");
// goes to next line end
cx.simulate_shared_keystrokes(["2", "$"]).await;
cx.assert_shared_state("aa\nbˇb\ncc").await;
cx.simulate_shared_keystrokes("2 $").await;
cx.shared_state().await.assert_eq("aa\nbˇb\ncc");
// try to exceed the final line.
cx.simulate_shared_keystrokes(["4", "$"]).await;
cx.assert_shared_state("aa\nbb\ncˇc").await;
cx.simulate_shared_keystrokes("4 $").await;
cx.shared_state().await.assert_eq("aa\nbb\ncˇc");
}
#[gpui::test]
@ -1148,34 +1293,22 @@ mod test {
]);
});
cx.assert_binding_normal(
["w"],
indoc! {"ˇassert_binding"},
indoc! {"assert_ˇbinding"},
);
cx.assert_binding_normal("w", indoc! {"ˇassert_binding"}, indoc! {"assert_ˇbinding"});
// Special case: In 'cw', 'w' acts like 'e'
cx.assert_binding(
["c", "w"],
"c w",
indoc! {"ˇassert_binding"},
Mode::Normal,
indoc! {"ˇ_binding"},
Mode::Insert,
);
cx.assert_binding_normal(
["e"],
indoc! {"ˇassert_binding"},
indoc! {"asserˇt_binding"},
);
cx.assert_binding_normal("e", indoc! {"ˇassert_binding"}, indoc! {"asserˇt_binding"});
cx.assert_binding_normal("b", indoc! {"assert_ˇbinding"}, indoc! {"ˇassert_binding"});
cx.assert_binding_normal(
["b"],
indoc! {"assert_ˇbinding"},
indoc! {"ˇassert_binding"},
);
cx.assert_binding_normal(
["g", "e"],
"g e",
indoc! {"assert_bindinˇg"},
indoc! {"asserˇt_binding"},
);

View File

@ -111,35 +111,35 @@ mod 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;
cx.simulate_shared_keystrokes("~").await;
cx.shared_state().await.assert_eq("AˇbC\n");
cx.simulate_shared_keystrokes("2 ~").await;
cx.shared_state().await.assert_eq("ABˇc\n");
// 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;
cx.simulate_shared_keystrokes("~").await;
cx.shared_state().await.assert_eq("a😀CˇDé1*F\n");
// works with multibyte characters
cx.simulate_shared_keystrokes(["~"]).await;
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;
cx.simulate_shared_keystrokes("4 ~").await;
cx.shared_state().await.assert_eq("ac😀É1ˇ*F\n");
// 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;
cx.simulate_shared_keystrokes("shift-v ~").await;
cx.shared_state().await.assert_eq("ˇABc\n");
// 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;
cx.simulate_shared_keystrokes("ctrl-v j ~").await;
cx.shared_state().await.assert_eq("ˇAa\nBb\ncc");
// works with multiple cursors (zed only)
cx.set_state("aˇßcdˇe\n", Mode::Normal);
cx.simulate_keystroke("~");
cx.simulate_keystrokes("~");
cx.assert_state("aSSˇcdˇE\n", Mode::Normal);
}
@ -148,18 +148,18 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
// works in visual mode
cx.set_shared_state("a😀C«dÉ1*fˇ»\n").await;
cx.simulate_shared_keystrokes(["U"]).await;
cx.assert_shared_state("a😀CˇDÉ1*F\n").await;
cx.simulate_shared_keystrokes("U").await;
cx.shared_state().await.assert_eq("a😀CˇDÉ1*F\n");
// works with line selections
cx.set_shared_state("abˇC\n").await;
cx.simulate_shared_keystrokes(["shift-v", "U"]).await;
cx.assert_shared_state("ˇABC\n").await;
cx.simulate_shared_keystrokes("shift-v U").await;
cx.shared_state().await.assert_eq("ˇABC\n");
// works in visual block mode
cx.set_shared_state("ˇaa\nbb\ncc").await;
cx.simulate_shared_keystrokes(["ctrl-v", "j", "U"]).await;
cx.assert_shared_state("ˇAa\nBb\ncc").await;
cx.simulate_shared_keystrokes("ctrl-v j U").await;
cx.shared_state().await.assert_eq("ˇAa\nBb\ncc");
}
#[gpui::test]
@ -167,17 +167,17 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
// works in visual mode
cx.set_shared_state("A😀c«DÉ1*fˇ»\n").await;
cx.simulate_shared_keystrokes(["u"]).await;
cx.assert_shared_state("A😀cˇdé1*f\n").await;
cx.simulate_shared_keystrokes("u").await;
cx.shared_state().await.assert_eq("A😀cˇdé1*f\n");
// works with line selections
cx.set_shared_state("ABˇc\n").await;
cx.simulate_shared_keystrokes(["shift-v", "u"]).await;
cx.assert_shared_state("ˇabc\n").await;
cx.simulate_shared_keystrokes("shift-v u").await;
cx.shared_state().await.assert_eq("ˇabc\n");
// works in visual block mode
cx.set_shared_state("ˇAa\nBb\nCc").await;
cx.simulate_shared_keystrokes(["ctrl-v", "j", "u"]).await;
cx.assert_shared_state("ˇaa\nbb\nCc").await;
cx.simulate_shared_keystrokes("ctrl-v j u").await;
cx.shared_state().await.assert_eq("ˇaa\nbb\nCc");
}
}

View File

@ -169,329 +169,401 @@ mod test {
#[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! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate("c h", "Teˇst").await.assert_matches();
cx.simulate("c h", "Tˇest").await.assert_matches();
cx.simulate("c h", "ˇTest").await.assert_matches();
cx.simulate(
"c h",
indoc! {"
Test
ˇtest"})
.await;
ˇtest"},
)
.await
.assert_matches();
}
#[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! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate("c backspace", "Teˇst").await.assert_matches();
cx.simulate("c backspace", "Tˇest").await.assert_matches();
cx.simulate("c backspace", "ˇTest").await.assert_matches();
cx.simulate(
"c backspace",
indoc! {"
Test
ˇtest"})
.await;
ˇtest"},
)
.await
.assert_matches();
}
#[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;
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate("c l", "Teˇst").await.assert_matches();
cx.simulate("c l", "Tesˇt").await.assert_matches();
}
#[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("Tesˇt test").await;
cx.assert(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate("c w", "Teˇst").await.assert_matches();
cx.simulate("c w", "Tˇest test").await.assert_matches();
cx.simulate("c w", "Testˇ test").await.assert_matches();
cx.simulate("c w", "Tesˇt test").await.assert_matches();
cx.simulate(
"c w",
indoc! {"
Test teˇst
test"})
.await;
cx.assert(indoc! {"
test"},
)
.await
.assert_matches();
cx.simulate(
"c w",
indoc! {"
Test tesˇt
test"})
.await;
cx.assert(indoc! {"
test"},
)
.await
.assert_matches();
cx.simulate(
"c w",
indoc! {"
Test test
ˇ
test"})
.await;
test"},
)
.await
.assert_matches();
let mut cx = cx.binding(["c", "shift-w"]);
cx.assert("Test teˇst-test test").await;
cx.simulate("c shift-w", "Test teˇst-test test")
.await
.assert_matches();
}
#[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! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate("c e", "Teˇst Test").await.assert_matches();
cx.simulate("c e", "Tˇest test").await.assert_matches();
cx.simulate(
"c e",
indoc! {"
Test teˇst
test"})
.await;
cx.assert(indoc! {"
test"},
)
.await
.assert_matches();
cx.simulate(
"c e",
indoc! {"
Test tesˇt
test"})
.await;
cx.assert(indoc! {"
test"},
)
.await
.assert_matches();
cx.simulate(
"c e",
indoc! {"
Test test
ˇ
test"})
.await;
test"},
)
.await
.assert_matches();
let mut cx = cx.binding(["c", "shift-e"]);
cx.assert("Test teˇst-test test").await;
cx.simulate("c shift-e", "Test teˇst-test test")
.await
.assert_matches();
}
#[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! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate("c b", "Teˇst Test").await.assert_matches();
cx.simulate("c b", "Test ˇtest").await.assert_matches();
cx.simulate("c b", "Test1 test2 ˇtest3")
.await
.assert_matches();
cx.simulate(
"c b",
indoc! {"
Test test
ˇtest"})
.await;
cx.assert(indoc! {"
ˇtest"},
)
.await
.assert_matches();
cx.simulate(
"c b",
indoc! {"
Test test
ˇ
test"})
.await;
test"},
)
.await
.assert_matches();
let mut cx = cx.binding(["c", "shift-b"]);
cx.assert("Test test-test ˇtest").await;
cx.simulate("c shift-b", "Test test-test ˇtest")
.await
.assert_matches();
}
#[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! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate(
"c $",
indoc! {"
The qˇuick
brown fox"})
.await;
cx.assert(indoc! {"
brown fox"},
)
.await
.assert_matches();
cx.simulate(
"c $",
indoc! {"
The quick
ˇ
brown fox"})
.await;
brown fox"},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_change_0(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.assert_neovim_compatible(
cx.simulate(
"c 0",
indoc! {"
The qˇuick
brown fox"},
["c", "0"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"c 0",
indoc! {"
The quick
ˇ
brown fox"},
["c", "0"],
)
.await;
.await
.assert_matches();
}
#[gpui::test]
async fn test_change_k(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.assert_neovim_compatible(
cx.simulate(
"c k",
indoc! {"
The quick
brown ˇfox
jumps over"},
["c", "k"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"c k",
indoc! {"
The quick
brown fox
jumps ˇover"},
["c", "k"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"c k",
indoc! {"
The qˇuick
brown fox
jumps over"},
["c", "k"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"c k",
indoc! {"
ˇ
brown fox
jumps over"},
["c", "k"],
)
.await;
.await
.assert_matches();
}
#[gpui::test]
async fn test_change_j(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.assert_neovim_compatible(
cx.simulate(
"c j",
indoc! {"
The quick
brown ˇfox
jumps over"},
["c", "j"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"c j",
indoc! {"
The quick
brown fox
jumps ˇover"},
["c", "j"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"c j",
indoc! {"
The qˇuick
brown fox
jumps over"},
["c", "j"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"c j",
indoc! {"
The quick
brown fox
ˇ"},
["c", "j"],
)
.await;
.await
.assert_matches();
}
#[gpui::test]
async fn test_change_end_of_document(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.assert_neovim_compatible(
cx.simulate(
"c shift-g",
indoc! {"
The quick
brownˇ fox
jumps over
the lazy"},
["c", "shift-g"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"c shift-g",
indoc! {"
The quick
brownˇ fox
jumps over
the lazy"},
["c", "shift-g"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"c shift-g",
indoc! {"
The quick
brown fox
jumps over
the lˇazy"},
["c", "shift-g"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"c shift-g",
indoc! {"
The quick
brown fox
jumps over
ˇ"},
["c", "shift-g"],
)
.await;
.await
.assert_matches();
}
#[gpui::test]
async fn test_change_cc(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.assert_neovim_compatible(
cx.simulate(
"c c",
indoc! {"
The quick
brownˇ fox
jumps over
the lazy"},
["c", "c"],
)
.await;
.await
.assert_matches();
cx.assert_neovim_compatible(
cx.simulate(
"c c",
indoc! {"
ˇThe quick
brown fox
jumps over
the lazy"},
["c", "c"],
)
.await;
.await
.assert_matches();
cx.assert_neovim_compatible(
cx.simulate(
"c c",
indoc! {"
The quick
broˇwn fox
jumˇps over
jumps over
the lazy"},
["c", "c"],
)
.await;
.await
.assert_matches();
}
#[gpui::test]
async fn test_change_gg(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.assert_neovim_compatible(
cx.simulate(
"c g g",
indoc! {"
The quick
brownˇ fox
jumps over
the lazy"},
["c", "g", "g"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"c g g",
indoc! {"
The quick
brown fox
jumps over
the lˇazy"},
["c", "g", "g"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"c g g",
indoc! {"
The qˇuick
brown fox
jumps over
the lazy"},
["c", "g", "g"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"c g g",
indoc! {"
ˇ
brown fox
jumps over
the lazy"},
["c", "g", "g"],
)
.await;
.await
.assert_matches();
}
#[gpui::test]
@ -499,8 +571,8 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
for count in 1..=5 {
cx.assert_binding_matches_all(
["c", &count.to_string(), "j"],
cx.simulate_at_each_offset(
&format!("c {count} j"),
indoc! {"
ˇThe quˇickˇ browˇn
ˇ
@ -508,7 +580,8 @@ mod test {
ˇthe lazy dog
"},
)
.await;
.await
.assert_matches();
}
}
@ -517,8 +590,8 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
for count in 1..=5 {
cx.assert_binding_matches_all(
["c", &count.to_string(), "l"],
cx.simulate_at_each_offset(
&format!("c {count} l"),
indoc! {"
ˇThe quˇickˇ browˇn
ˇ
@ -526,7 +599,8 @@ mod test {
ˇthe lazy dog
"},
)
.await;
.await
.assert_matches();
}
}
@ -535,16 +609,17 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
for count in 1..=5 {
for marked_text in cx.each_marked_position(indoc! {"
cx.simulate_at_each_offset(
&format!("c {count} b"),
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;
}
"},
)
.await
.assert_matches()
}
}
@ -553,8 +628,8 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
for count in 1..=5 {
cx.assert_binding_matches_all(
["c", &count.to_string(), "e"],
cx.simulate_at_each_offset(
&format!("c {count} e"),
indoc! {"
ˇThe quˇickˇ browˇn
ˇ
@ -562,7 +637,8 @@ mod test {
ˇthe lazy dog
"},
)
.await;
.await
.assert_matches();
}
}
}

View File

@ -158,280 +158,358 @@ mod test {
use crate::{
state::Mode,
test::{ExemptionFeatures, NeovimBackedTestContext, VimTestContext},
test::{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! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate("d h", "Teˇst").await.assert_matches();
cx.simulate("d h", "Tˇest").await.assert_matches();
cx.simulate("d h", "ˇTest").await.assert_matches();
cx.simulate(
"d h",
indoc! {"
Test
ˇtest"})
.await;
ˇtest"},
)
.await
.assert_matches();
}
#[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! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate("d l", "ˇTest").await.assert_matches();
cx.simulate("d l", "Teˇst").await.assert_matches();
cx.simulate("d l", "Tesˇt").await.assert_matches();
cx.simulate(
"d l",
indoc! {"
Tesˇt
test"})
.await;
test"},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_delete_w(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.assert_neovim_compatible(
cx.simulate(
"d w",
indoc! {"
Test tesˇt
test"},
["d", "w"],
)
.await;
.await
.assert_matches();
cx.assert_neovim_compatible("Teˇst", ["d", "w"]).await;
cx.assert_neovim_compatible("Tˇest test", ["d", "w"]).await;
cx.assert_neovim_compatible(
cx.simulate("d w", "Teˇst").await.assert_matches();
cx.simulate("d w", "Tˇest test").await.assert_matches();
cx.simulate(
"d w",
indoc! {"
Test teˇst
test"},
["d", "w"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"d w",
indoc! {"
Test tesˇt
test"},
["d", "w"],
)
.await;
.await
.assert_matches();
cx.assert_neovim_compatible(
cx.simulate(
"d w",
indoc! {"
Test test
ˇ
test"},
["d", "w"],
)
.await;
.await
.assert_matches();
let mut cx = cx.binding(["d", "shift-w"]);
cx.assert_neovim_compatible("Test teˇst-test test", ["d", "shift-w"])
.await;
cx.simulate("d shift-w", "Test teˇst-test test")
.await
.assert_matches();
}
#[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(
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate("d e", "Teˇst Test\n").await.assert_matches();
cx.simulate("d e", "Tˇest test\n").await.assert_matches();
cx.simulate(
"d e",
indoc! {"
Test test
ˇ
Test teˇst
test"},
ExemptionFeatures::OperatorLastNewlineRemains,
)
.await;
.await
.assert_matches();
cx.simulate(
"d e",
indoc! {"
Test tesˇt
test"},
)
.await
.assert_matches();
let mut cx = cx.binding(["d", "shift-e"]);
cx.assert("Test teˇst-test test").await;
cx.simulate("d e", "Test teˇst-test test")
.await
.assert_matches();
}
#[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! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate("d b", "Teˇst Test").await.assert_matches();
cx.simulate("d b", "Test ˇtest").await.assert_matches();
cx.simulate("d b", "Test1 test2 ˇtest3")
.await
.assert_matches();
cx.simulate(
"d b",
indoc! {"
Test test
ˇtest"})
.await;
cx.assert(indoc! {"
ˇtest"},
)
.await
.assert_matches();
cx.simulate(
"d b",
indoc! {"
Test test
ˇ
test"})
.await;
test"},
)
.await
.assert_matches();
let mut cx = cx.binding(["d", "shift-b"]);
cx.assert("Test test-test ˇtest").await;
cx.simulate("d shift-b", "Test test-test ˇtest")
.await
.assert_matches();
}
#[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! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate(
"d $",
indoc! {"
The qˇuick
brown fox"})
.await;
cx.assert(indoc! {"
brown fox"},
)
.await
.assert_matches();
cx.simulate(
"d $",
indoc! {"
The quick
ˇ
brown fox"})
.await;
brown fox"},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_delete_0(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "0"]);
cx.assert(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate(
"d 0",
indoc! {"
The qˇuick
brown fox"})
.await;
cx.assert(indoc! {"
brown fox"},
)
.await
.assert_matches();
cx.simulate(
"d 0",
indoc! {"
The quick
ˇ
brown fox"})
.await;
brown fox"},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_delete_k(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "k"]);
cx.assert(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate(
"d k",
indoc! {"
The quick
brown ˇfox
jumps over"})
.await;
cx.assert(indoc! {"
jumps over"},
)
.await
.assert_matches();
cx.simulate(
"d k",
indoc! {"
The quick
brown fox
jumps ˇover"})
.await;
cx.assert(indoc! {"
jumps ˇover"},
)
.await
.assert_matches();
cx.simulate(
"d k",
indoc! {"
The qˇuick
brown fox
jumps over"})
.await;
cx.assert(indoc! {"
jumps over"},
)
.await
.assert_matches();
cx.simulate(
"d k",
indoc! {"
ˇbrown fox
jumps over"})
.await;
jumps over"},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_delete_j(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await.binding(["d", "j"]);
cx.assert(indoc! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate(
"d j",
indoc! {"
The quick
brown ˇfox
jumps over"})
.await;
cx.assert(indoc! {"
jumps over"},
)
.await
.assert_matches();
cx.simulate(
"d j",
indoc! {"
The quick
brown fox
jumps ˇover"})
.await;
cx.assert(indoc! {"
jumps ˇover"},
)
.await
.assert_matches();
cx.simulate(
"d j",
indoc! {"
The qˇuick
brown fox
jumps over"})
.await;
cx.assert(indoc! {"
jumps over"},
)
.await
.assert_matches();
cx.simulate(
"d j",
indoc! {"
The quick
brown fox
ˇ"})
.await;
ˇ"},
)
.await
.assert_matches();
}
#[gpui::test]
async fn test_delete_end_of_document(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.assert_neovim_compatible(
cx.simulate(
"d shift-g",
indoc! {"
The quick
brownˇ fox
jumps over
the lazy"},
["d", "shift-g"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"d shift-g",
indoc! {"
The quick
brownˇ fox
jumps over
the lazy"},
["d", "shift-g"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"d shift-g",
indoc! {"
The quick
brown fox
jumps over
the lˇazy"},
["d", "shift-g"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"d shift-g",
indoc! {"
The quick
brown fox
jumps over
ˇ"},
["d", "shift-g"],
)
.await;
.await
.assert_matches();
}
#[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(
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate(
"d g g",
indoc! {"
The quick
brownˇ fox
jumps over
the lazy"},
["d", "g", "g"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"d g g",
indoc! {"
The quick
brown fox
jumps over
the lˇazy"},
["d", "g", "g"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"d g g",
indoc! {"
The qˇuick
brown fox
jumps over
the lazy"},
["d", "g", "g"],
)
.await;
cx.assert_neovim_compatible(
.await
.assert_matches();
cx.simulate(
"d g g",
indoc! {"
ˇ
brown fox
jumps over
the lazy"},
["d", "g", "g"],
)
.await;
.await
.assert_matches();
}
#[gpui::test]
@ -446,7 +524,7 @@ mod test {
);
// Canceling operator twice reverts to normal mode with no active operator
cx.simulate_keystrokes(["d", "escape", "k"]);
cx.simulate_keystrokes("d escape k");
assert_eq!(cx.active_operator(), None);
assert_eq!(cx.mode(), Mode::Normal);
cx.assert_editor_state(indoc! {"
@ -467,7 +545,7 @@ mod test {
);
// Canceling operator twice reverts to normal mode with no active operator
cx.simulate_keystrokes(["d", "y"]);
cx.simulate_keystrokes("d y");
assert_eq!(cx.active_operator(), None);
assert_eq!(cx.mode(), Mode::Normal);
}
@ -480,20 +558,18 @@ mod test {
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.simulate_shared_keystrokes("d 2 d").await;
cx.shared_state().await.assert_eq(indoc! {"
the ˇlazy dog"});
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.simulate_shared_keystrokes("2 d d").await;
cx.shared_state().await.assert_eq(indoc! {"
the ˇlazy dog"});
cx.set_shared_state(indoc! {"
The ˇquick brown
@ -502,16 +578,15 @@ mod test {
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.simulate_shared_keystrokes("2 d 2 d").await;
cx.shared_state().await.assert_eq(indoc! {"
the ˇlazy dog"});
}
#[gpui::test]
async fn test_delete_to_adjacent_character(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.assert_neovim_compatible("ˇax", ["d", "t", "x"]).await;
cx.assert_neovim_compatible("aˇx", ["d", "t", "x"]).await;
cx.simulate("d t x", "ˇax").await.assert_matches();
cx.simulate("d t x", "x").await.assert_matches();
}
}

View File

@ -191,33 +191,27 @@ mod test {
"})
.await;
cx.simulate_shared_keystrokes(["ctrl-a"]).await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("ctrl-a").await;
cx.shared_state().await.assert_eq(indoc! {"
1ˇ3
"})
.await;
cx.simulate_shared_keystrokes(["ctrl-x"]).await;
cx.assert_shared_state(indoc! {"
"});
cx.simulate_shared_keystrokes("ctrl-x").await;
cx.shared_state().await.assert_eq(indoc! {"
1ˇ2
"})
.await;
"});
cx.simulate_shared_keystrokes(["9", "9", "ctrl-a"]).await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("9 9 ctrl-a").await;
cx.shared_state().await.assert_eq(indoc! {"
11ˇ1
"})
.await;
cx.simulate_shared_keystrokes(["1", "1", "1", "ctrl-x"])
.await;
cx.assert_shared_state(indoc! {"
"});
cx.simulate_shared_keystrokes("1 1 1 ctrl-x").await;
cx.shared_state().await.assert_eq(indoc! {"
ˇ0
"})
.await;
cx.simulate_shared_keystrokes(["."]).await;
cx.assert_shared_state(indoc! {"
"});
cx.simulate_shared_keystrokes(".").await;
cx.shared_state().await.assert_eq(indoc! {"
-11ˇ1
"})
.await;
"});
}
#[gpui::test]
@ -229,16 +223,14 @@ mod test {
"})
.await;
cx.simulate_shared_keystrokes(["ctrl-a"]).await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("ctrl-a").await;
cx.shared_state().await.assert_eq(indoc! {"
1.ˇ3
"})
.await;
cx.simulate_shared_keystrokes(["ctrl-x"]).await;
cx.assert_shared_state(indoc! {"
"});
cx.simulate_shared_keystrokes("ctrl-x").await;
cx.shared_state().await.assert_eq(indoc! {"
1.ˇ2
"})
.await;
"});
}
#[gpui::test]
@ -250,33 +242,32 @@ mod test {
"})
.await;
cx.simulate_shared_keystrokes(["ctrl-a"]).await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("ctrl-a").await;
cx.shared_state().await.assert_eq(indoc! {"
111..ˇ3
"})
.await;
cx.simulate_shared_keystrokes(["ctrl-x"]).await;
cx.assert_shared_state(indoc! {"
"});
cx.simulate_shared_keystrokes("ctrl-x").await;
cx.shared_state().await.assert_eq(indoc! {"
111..ˇ2
"})
.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.simulate("ctrl-a", "ˇ total: 0xff")
.await
.assert_matches();
cx.simulate("ctrl-x", "ˇ total: 0xff")
.await
.assert_matches();
cx.simulate("ctrl-x", "ˇ total: 0xFF")
.await
.assert_matches();
cx.simulate("ctrl-a", "(ˇ0b10f)").await.assert_matches();
cx.simulate("ctrl-a", "ˇ-1").await.assert_matches();
cx.simulate("ctrl-a", "banˇana").await.assert_matches();
}
#[gpui::test]
@ -291,33 +282,28 @@ mod test {
1"})
.await;
cx.simulate_shared_keystrokes(["j", "v", "shift-g", "g", "ctrl-a"])
.await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("j v shift-g g ctrl-a").await;
cx.shared_state().await.assert_eq(indoc! {"
1
ˇ2
3 2
4
5"})
.await;
5"});
cx.simulate_shared_keystrokes(["shift-g", "ctrl-v", "g", "g"])
.await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("shift-g ctrl-v g g").await;
cx.shared_state().await.assert_eq(indoc! {"
«1ˇ»
«2ˇ»
«3ˇ» 2
«4ˇ»
«5ˇ»"})
.await;
«5ˇ»"});
cx.simulate_shared_keystrokes(["g", "ctrl-x"]).await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("g ctrl-x").await;
cx.shared_state().await.assert_eq(indoc! {"
ˇ0
0
0 2
0
0"})
.await;
0"});
}
}

View File

@ -246,31 +246,29 @@ mod test {
fox ˇjumps over
the lazy dog"})
.await;
cx.simulate_shared_keystrokes(["v", "w", "y"]).await;
cx.assert_shared_clipboard("jumps o").await;
cx.simulate_shared_keystrokes("v w y").await;
cx.shared_clipboard().await.assert_eq("jumps o");
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! {"
cx.simulate_shared_keystrokes("p").await;
cx.shared_state().await.assert_eq(indoc! {"
The quick brown
fox jumps overjumps ˇo
the lazy dog"})
.await;
the lazy dog"});
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! {"
cx.simulate_shared_keystrokes("shift-p").await;
cx.shared_state().await.assert_eq(indoc! {"
The quick brown
fox jumps ovejumps ˇor
the lazy dog"})
.await;
the lazy dog"});
// line mode
cx.set_shared_state(indoc! {"
@ -278,25 +276,22 @@ mod test {
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! {"
cx.simulate_shared_keystrokes("d d").await;
cx.shared_clipboard().await.assert_eq("fox jumps over\n");
cx.shared_state().await.assert_eq(indoc! {"
The quick brown
the laˇzy dog"})
.await;
cx.simulate_shared_keystroke("p").await;
cx.assert_shared_state(indoc! {"
the laˇzy dog"});
cx.simulate_shared_keystrokes("p").await;
cx.shared_state().await.assert_eq(indoc! {"
The quick brown
the lazy dog
ˇfox jumps over"})
.await;
cx.simulate_shared_keystrokes(["k", "shift-p"]).await;
cx.assert_shared_state(indoc! {"
ˇfox jumps over"});
cx.simulate_shared_keystrokes("k shift-p").await;
cx.shared_state().await.assert_eq(indoc! {"
The quick brown
ˇfox jumps over
the lazy dog
fox jumps over"})
.await;
fox jumps over"});
// multiline, cursor to first character of pasted text.
cx.set_shared_state(indoc! {"
@ -304,23 +299,21 @@ mod test {
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_keystrokes("v j y").await;
cx.shared_clipboard().await.assert_eq("over\nthe lazy do");
cx.simulate_shared_keystroke("p").await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("p").await;
cx.shared_state().await.assert_eq(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 lazy dog"});
cx.simulate_shared_keystrokes("u shift-p").await;
cx.shared_state().await.assert_eq(indoc! {"
The quick brown
fox jumps ˇover
the lazy doover
the lazy dog"})
.await;
the lazy dog"});
}
#[gpui::test]
@ -340,7 +333,7 @@ mod test {
the lazy dog"},
Mode::Normal,
);
cx.simulate_keystrokes(["v", "i", "w", "y"]);
cx.simulate_keystrokes("v i w y");
cx.assert_state(
indoc! {"
The quick brown
@ -348,7 +341,7 @@ mod test {
the lazy dog"},
Mode::Normal,
);
cx.simulate_keystroke("p");
cx.simulate_keystrokes("p");
cx.assert_state(
indoc! {"
The quick brown
@ -377,7 +370,7 @@ mod test {
the lazy dog"},
Mode::Normal,
);
cx.simulate_keystrokes(["v", "i", "w", "y"]);
cx.simulate_keystrokes("v i w y");
cx.assert_state(
indoc! {"
The quick brown
@ -385,7 +378,7 @@ mod test {
the lazy dog"},
Mode::Normal,
);
cx.simulate_keystroke("p");
cx.simulate_keystrokes("p");
cx.assert_state(
indoc! {"
The quick brown
@ -397,7 +390,7 @@ mod test {
cx.read_from_clipboard().map(|item| item.text().clone()),
Some("jumps".into())
);
cx.simulate_keystrokes(["d", "d", "p"]);
cx.simulate_keystrokes("d d p");
cx.assert_state(
indoc! {"
The quick brown
@ -410,7 +403,7 @@ mod test {
Some("jumps".into())
);
cx.write_to_clipboard(ClipboardItem::new("test-copy".to_string()));
cx.simulate_keystroke("shift-p");
cx.simulate_keystrokes("shift-p");
cx.assert_state(
indoc! {"
The quick brown
@ -430,38 +423,31 @@ mod test {
fox jˇumps over
the lazy dog"})
.await;
cx.simulate_shared_keystrokes(["v", "i", "w", "y"]).await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("v i w y").await;
cx.shared_state().await.assert_eq(indoc! {"
The quick brown
fox ˇjumps over
the lazy dog"})
.await;
the lazy dog"});
// paste in visual mode
cx.simulate_shared_keystrokes(["w", "v", "i", "w", "p"])
.await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("w v i w p").await;
cx.shared_state().await.assert_eq(indoc! {"
The quick brown
fox jumps jumpˇs
the lazy dog"})
.await;
cx.assert_shared_clipboard("over").await;
the lazy dog"});
cx.shared_clipboard().await.assert_eq("over");
// paste in visual line mode
cx.simulate_shared_keystrokes(["up", "shift-v", "shift-p"])
.await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("up shift-v shift-p").await;
cx.shared_state().await.assert_eq(indoc! {"
ˇover
fox jumps jumps
the lazy dog"})
.await;
cx.assert_shared_clipboard("over").await;
the lazy dog"});
cx.shared_clipboard().await.assert_eq("over");
// paste in visual block mode
cx.simulate_shared_keystrokes(["ctrl-v", "down", "down", "p"])
.await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("ctrl-v down down p").await;
cx.shared_state().await.assert_eq(indoc! {"
oveˇrver
overox jumps jumps
overhe lazy dog"})
.await;
overhe lazy dog"});
// copy in visual line mode
cx.set_shared_state(indoc! {"
@ -469,40 +455,33 @@ mod test {
fox juˇmps over
the lazy dog"})
.await;
cx.simulate_shared_keystrokes(["shift-v", "d"]).await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("shift-v d").await;
cx.shared_state().await.assert_eq(indoc! {"
The quick brown
the laˇzy dog"})
.await;
the laˇzy dog"});
// paste in visual mode
cx.simulate_shared_keystrokes(["v", "i", "w", "p"]).await;
cx.assert_shared_state(
&indoc! {"
cx.simulate_shared_keystrokes("v i w p").await;
cx.shared_state().await.assert_eq(&indoc! {"
The quick brown
the_
the
ˇfox jumps over
_dog"}
.replace('_', " "), // Hack for trailing whitespace
)
.await;
cx.assert_shared_clipboard("lazy").await;
dog"});
cx.shared_clipboard().await.assert_eq("lazy");
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! {"
cx.simulate_shared_keystrokes("shift-v d").await;
cx.shared_state().await.assert_eq(indoc! {"
The quick brown
the laˇzy dog"})
.await;
the laˇzy dog"});
// paste in visual line mode
cx.simulate_shared_keystrokes(["k", "shift-v", "p"]).await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("k shift-v p").await;
cx.shared_state().await.assert_eq(indoc! {"
ˇfox jumps over
the lazy dog"})
.await;
cx.assert_shared_clipboard("The quick brown\n").await;
the lazy dog"});
cx.shared_clipboard().await.assert_eq("The quick brown\n");
}
#[gpui::test]
@ -514,47 +493,39 @@ mod test {
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! {"
cx.simulate_shared_keystrokes("ctrl-v 2 j y").await;
cx.shared_clipboard().await.assert_eq("q\nj\nl");
cx.simulate_shared_keystrokes("p").await;
cx.shared_state().await.assert_eq(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 llazy dog"});
cx.simulate_shared_keystrokes("v i w shift-p").await;
cx.shared_state().await.assert_eq(indoc! {"
The ˇq brown
fox jjjumps over
the lllazy dog"})
.await;
cx.simulate_shared_keystrokes(["v", "i", "w", "shift-p"])
.await;
the lllazy dog"});
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! {"
cx.simulate_shared_keystrokes("ctrl-v j y").await;
cx.shared_clipboard().await.assert_eq("q\nj");
cx.simulate_shared_keystrokes("l ctrl-v 2 j shift-p").await;
cx.shared_state().await.assert_eq(indoc! {"
The qˇqick brown
fox jjmps over
the lzy dog"})
.await;
the lzy dog"});
cx.simulate_shared_keystrokes(["shift-v", "p"]).await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("shift-v p").await;
cx.shared_state().await.assert_eq(indoc! {"
ˇq
j
fox jjmps over
the lzy dog"})
.await;
the lzy dog"});
}
#[gpui::test]
@ -568,7 +539,7 @@ mod test {
"},
Mode::Normal,
);
cx.simulate_keystrokes(["o", "a", "(", ")", "{", "escape"]);
cx.simulate_keystrokes("o a ( ) { escape");
cx.assert_state(
indoc! {"
class A {
@ -578,7 +549,7 @@ mod test {
Mode::Normal,
);
// cursor goes to the first non-blank character in the line;
cx.simulate_keystrokes(["y", "y", "p"]);
cx.simulate_keystrokes("y y p");
cx.assert_state(
indoc! {"
class A {
@ -589,7 +560,7 @@ mod test {
Mode::Normal,
);
// indentation is preserved when pasting
cx.simulate_keystrokes(["u", "shift-v", "up", "y", "shift-p"]);
cx.simulate_keystrokes("u shift-v up y shift-p");
cx.assert_state(
indoc! {"
ˇclass A {
@ -612,16 +583,15 @@ mod test {
three
"})
.await;
cx.simulate_shared_keystrokes(["y", "y", "3", "p"]).await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("y y 3 p").await;
cx.shared_state().await.assert_eq(indoc! {"
one
ˇone
one
one
two
three
"})
.await;
"});
cx.set_shared_state(indoc! {"
one
@ -629,13 +599,11 @@ mod test {
three
"})
.await;
cx.simulate_shared_keystrokes(["y", "$", "$", "3", "p"])
.await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("y $ $ 3 p").await;
cx.shared_state().await.assert_eq(indoc! {"
one
twotwotwotwˇo
three
"})
.await;
"});
}
}

View File

@ -222,32 +222,32 @@ mod test {
// "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;
cx.simulate_shared_keystrokes("o w o r l d escape").await;
cx.shared_state().await.assert_eq("hello\nworlˇd");
cx.simulate_shared_keystrokes(".").await;
cx.shared_state().await.assert_eq("hello\nworld\nworlˇd");
// "d"
cx.simulate_shared_keystrokes(["^", "d", "f", "o"]).await;
cx.simulate_shared_keystrokes(["g", "g", "."]).await;
cx.assert_shared_state("ˇ\nworld\nrld").await;
cx.simulate_shared_keystrokes("^ d f o").await;
cx.simulate_shared_keystrokes("g g .").await;
cx.shared_state().await.assert_eq("ˇ\nworld\nrld");
// "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;
cx.simulate_shared_keystrokes("j y y p").await;
cx.simulate_shared_keystrokes("shift-g y y .").await;
cx.shared_state()
.await
.assert_eq("\nworld\nworld\nrld\nˇrld");
// "~" (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.simulate_shared_keystrokes("2 ~ .").await;
cx.set_shared_state("THE ˇquick brown fox").await;
cx.simulate_shared_keystrokes(["3", "."]).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;
cx.simulate_shared_keystrokes(".").await;
cx.shared_state().await.assert_eq("THE QUICK ˇbrown fox");
}
#[gpui::test]
@ -255,16 +255,16 @@ mod test {
let mut cx = VimTestContext::new(cx, true).await;
cx.set_state("hˇllo", Mode::Normal);
cx.simulate_keystrokes(["i"]);
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.simulate_keystrokes("escape");
cx.assert_state("hˇällo", Mode::Normal);
cx.simulate_keystrokes(["."]);
cx.simulate_keystrokes(".");
cx.assert_state("hˇäällo", Mode::Normal);
}
@ -316,11 +316,11 @@ mod test {
},
])))
});
cx.simulate_keystrokes(["a", "."]);
cx.simulate_keystrokes("a .");
request.next().await;
cx.condition(|editor, _| editor.context_menu_visible())
.await;
cx.simulate_keystrokes(["down", "enter", "!", "escape"]);
cx.simulate_keystrokes("down enter ! escape");
cx.assert_state(
indoc! {"
@ -330,7 +330,7 @@ mod test {
"},
Mode::Normal,
);
cx.simulate_keystrokes(["j", "."]);
cx.simulate_keystrokes("j .");
cx.assert_state(
indoc! {"
one.second!
@ -352,27 +352,23 @@ mod test {
the lazy dog"
})
.await;
cx.simulate_shared_keystrokes(["v", "i", "w", "s", "o", "escape"])
.await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes("v i w s o escape").await;
cx.shared_state().await.assert_eq(indoc! {
"ˇo quick brown
fox jumps over
the lazy dog"
})
.await;
cx.simulate_shared_keystrokes(["j", "w", "."]).await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes("j w .").await;
cx.shared_state().await.assert_eq(indoc! {
"o quick brown
fox ˇops over
the lazy dog"
})
.await;
cx.simulate_shared_keystrokes(["f", "r", "."]).await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes("f r .").await;
cx.shared_state().await.assert_eq(indoc! {
"o quick brown
fox ops oveˇothe lazy dog"
})
.await;
});
// visual
cx.set_shared_state(indoc! {
@ -383,33 +379,29 @@ mod test {
the lazy dog"
})
.await;
cx.simulate_shared_keystrokes(["v", "j", "x"]).await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes("v j x").await;
cx.shared_state().await.assert_eq(indoc! {
"the ˇumps over
fox jumps over
fox jumps over
the lazy dog"
})
.await;
cx.simulate_shared_keystrokes(["."]).await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes(".").await;
cx.shared_state().await.assert_eq(indoc! {
"the ˇumps over
fox jumps over
the lazy dog"
})
.await;
cx.simulate_shared_keystrokes(["w", "."]).await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes("w .").await;
cx.shared_state().await.assert_eq(indoc! {
"the umps ˇumps over
the lazy dog"
})
.await;
cx.simulate_shared_keystrokes(["j", "."]).await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes("j .").await;
cx.shared_state().await.assert_eq(indoc! {
"the umps umps over
the ˇog"
})
.await;
});
// block mode (3 rows)
cx.set_shared_state(indoc! {
@ -418,21 +410,19 @@ mod test {
the lazy dog"
})
.await;
cx.simulate_shared_keystrokes(["ctrl-v", "j", "j", "shift-i", "o", "escape"])
cx.simulate_shared_keystrokes("ctrl-v j j shift-i o escape")
.await;
cx.assert_shared_state(indoc! {
cx.shared_state().await.assert_eq(indoc! {
"ˇothe quick brown
ofox jumps over
othe lazy dog"
})
.await;
cx.simulate_shared_keystrokes(["j", "4", "l", "."]).await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes("j 4 l .").await;
cx.shared_state().await.assert_eq(indoc! {
"othe quick brown
ofoxˇo jumps over
otheo lazy dog"
})
.await;
});
// line mode
cx.set_shared_state(indoc! {
@ -441,21 +431,19 @@ mod test {
the lazy dog"
})
.await;
cx.simulate_shared_keystrokes(["shift-v", "shift-r", "o", "escape"])
cx.simulate_shared_keystrokes("shift-v shift-r o escape")
.await;
cx.assert_shared_state(indoc! {
cx.shared_state().await.assert_eq(indoc! {
"ˇo
fox jumps over
the lazy dog"
})
.await;
cx.simulate_shared_keystrokes(["j", "."]).await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes("j .").await;
cx.shared_state().await.assert_eq(indoc! {
"o
ˇo
the lazy dog"
})
.await;
});
}
#[gpui::test]
@ -468,27 +456,24 @@ mod test {
the lazy dog"
})
.await;
cx.simulate_shared_keystrokes(["3", "d", "3", "l"]).await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes("3 d 3 l").await;
cx.shared_state().await.assert_eq(indoc! {
"ˇ brown
fox jumps over
the lazy dog"
})
.await;
cx.simulate_shared_keystrokes(["j", "."]).await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes("j .").await;
cx.shared_state().await.assert_eq(indoc! {
" brown
ˇ over
the lazy dog"
})
.await;
cx.simulate_shared_keystrokes(["j", "2", "."]).await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes("j 2 .").await;
cx.shared_state().await.assert_eq(indoc! {
" brown
over
ˇe lazy dog"
})
.await;
});
}
#[gpui::test]
@ -496,8 +481,8 @@ mod test {
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.simulate_keystrokes("4 i j cmd-shift-p escape");
cx.simulate_keystrokes("escape");
cx.assert_state("ˇjhello\n", Mode::Normal);
}
@ -506,11 +491,10 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.set_shared_state("ˇhello hello hello\n").await;
cx.simulate_shared_keystrokes(["c", "f", "o", "x", "escape"])
.await;
cx.assert_shared_state("ˇx hello hello\n").await;
cx.simulate_shared_keystrokes([":", "escape"]).await;
cx.simulate_shared_keystrokes(["."]).await;
cx.assert_shared_state("ˇx hello\n").await;
cx.simulate_shared_keystrokes("c f o x escape").await;
cx.shared_state().await.assert_eq("ˇx hello hello\n");
cx.simulate_shared_keystrokes(": escape").await;
cx.simulate_shared_keystrokes(".").await;
cx.shared_state().await.assert_eq("ˇx hello\n");
}
}

View File

@ -170,25 +170,25 @@ mod test {
cx.update_editor(|editor, cx| {
assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 0.))
});
cx.simulate_keystrokes(["ctrl-e"]);
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.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.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.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.simulate_keystrokes("ctrl-d");
cx.update_editor(|editor, cx| {
assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 3.0));
assert_eq!(
@ -198,11 +198,11 @@ mod test {
});
// does select in visual mode
cx.simulate_keystrokes(["g", "g"]);
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.simulate_keystrokes("v ctrl-d");
cx.update_editor(|editor, cx| {
assert_eq!(editor.snapshot(cx).scroll_position(), point(0., 3.0));
assert_eq!(
@ -234,18 +234,18 @@ mod test {
// 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;
cx.simulate_shared_keystrokes("4 j ctrl-d").await;
cx.shared_state().await.assert_matches();
cx.simulate_shared_keystrokes("ctrl-d").await;
cx.shared_state().await.assert_matches();
cx.simulate_shared_keystrokes("g g ctrl-d").await;
cx.shared_state().await.assert_matches();
// 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"])
cx.simulate_shared_keystrokes("ctrl-u").await;
cx.shared_state().await.assert_matches();
cx.simulate_shared_keystrokes("ctrl-d ctrl-d 4 j ctrl-u ctrl-u")
.await;
cx.assert_state_matches().await;
cx.shared_state().await.assert_matches();
}
}

View File

@ -523,34 +523,34 @@ mod test {
let mut cx = VimTestContext::new(cx, true).await;
cx.set_state("ˇhi\nhigh\nhi\n", Mode::Normal);
cx.simulate_keystrokes(["*"]);
cx.simulate_keystrokes("*");
cx.run_until_parked();
cx.assert_state("hi\nhigh\nˇhi\n", Mode::Normal);
cx.simulate_keystrokes(["*"]);
cx.simulate_keystrokes("*");
cx.run_until_parked();
cx.assert_state("ˇhi\nhigh\nhi\n", Mode::Normal);
cx.simulate_keystrokes(["#"]);
cx.simulate_keystrokes("#");
cx.run_until_parked();
cx.assert_state("hi\nhigh\nˇhi\n", Mode::Normal);
cx.simulate_keystrokes(["#"]);
cx.simulate_keystrokes("#");
cx.run_until_parked();
cx.assert_state("ˇhi\nhigh\nhi\n", Mode::Normal);
cx.simulate_keystrokes(["2", "*"]);
cx.simulate_keystrokes("2 *");
cx.run_until_parked();
cx.assert_state("ˇhi\nhigh\nhi\n", Mode::Normal);
cx.simulate_keystrokes(["g", "*"]);
cx.simulate_keystrokes("g *");
cx.run_until_parked();
cx.assert_state("hi\nˇhigh\nhi\n", Mode::Normal);
cx.simulate_keystrokes(["n"]);
cx.simulate_keystrokes("n");
cx.assert_state("hi\nhigh\nˇhi\n", Mode::Normal);
cx.simulate_keystrokes(["g", "#"]);
cx.simulate_keystrokes("g #");
cx.run_until_parked();
cx.assert_state("hi\nˇhigh\nhi\n", Mode::Normal);
}
@ -560,7 +560,7 @@ mod test {
let mut cx = VimTestContext::new(cx, true).await;
cx.set_state("aa\nbˇb\ncc\ncc\ncc\n", Mode::Normal);
cx.simulate_keystrokes(["/", "c", "c"]);
cx.simulate_keystrokes("/ c c");
let search_bar = cx.workspace(|workspace, cx| {
workspace
@ -587,50 +587,50 @@ mod test {
)
});
cx.simulate_keystrokes(["enter"]);
cx.simulate_keystrokes("enter");
cx.assert_state("aa\nbb\nˇcc\ncc\ncc\n", Mode::Normal);
// n to go to next/N to go to previous
cx.simulate_keystrokes(["n"]);
cx.simulate_keystrokes("n");
cx.assert_state("aa\nbb\ncc\nˇcc\ncc\n", Mode::Normal);
cx.simulate_keystrokes(["shift-n"]);
cx.simulate_keystrokes("shift-n");
cx.assert_state("aa\nbb\nˇcc\ncc\ncc\n", Mode::Normal);
// ?<enter> to go to previous
cx.simulate_keystrokes(["?", "enter"]);
cx.simulate_keystrokes("? enter");
cx.assert_state("aa\nbb\ncc\ncc\nˇcc\n", Mode::Normal);
cx.simulate_keystrokes(["?", "enter"]);
cx.simulate_keystrokes("? enter");
cx.assert_state("aa\nbb\ncc\nˇcc\ncc\n", Mode::Normal);
// /<enter> to go to next
cx.simulate_keystrokes(["/", "enter"]);
cx.simulate_keystrokes("/ enter");
cx.assert_state("aa\nbb\ncc\ncc\nˇcc\n", Mode::Normal);
// ?{search}<enter> to search backwards
cx.simulate_keystrokes(["?", "b", "enter"]);
cx.simulate_keystrokes("? b enter");
cx.assert_state("aa\nbˇb\ncc\ncc\ncc\n", Mode::Normal);
// works with counts
cx.simulate_keystrokes(["4", "/", "c"]);
cx.simulate_keystrokes(["enter"]);
cx.simulate_keystrokes("4 / c");
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"]);
cx.simulate_keystrokes(["enter"]);
cx.simulate_keystrokes("/ d");
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"]);
cx.simulate_keystrokes(["enter"]);
cx.simulate_keystrokes("/ b");
cx.simulate_keystrokes("enter");
cx.assert_state("aa\nˇbb\ndd\ncc\nbb\n", Mode::Normal);
// check that searching switches to normal mode if in visual mode
cx.set_state("ˇone two one", Mode::Normal);
cx.simulate_keystrokes(["v", "l", "l"]);
cx.simulate_keystrokes("v l l");
cx.assert_editor_state("«oneˇ» two one");
cx.simulate_keystrokes(["*"]);
cx.simulate_keystrokes("*");
cx.assert_state("one two ˇone", Mode::Normal);
}
@ -638,13 +638,13 @@ mod test {
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"]);
cx.simulate_keystrokes("cmd-f");
cx.run_until_parked();
cx.assert_editor_state("«oneˇ» one one one");
cx.simulate_keystrokes(["enter"]);
cx.simulate_keystrokes("enter");
cx.assert_editor_state("one «oneˇ» one one");
cx.simulate_keystrokes(["shift-enter"]);
cx.simulate_keystrokes("shift-enter");
cx.assert_editor_state("«oneˇ» one one one");
}
@ -653,9 +653,8 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.set_shared_state("ˇa.c. abcd a.c. abcd").await;
cx.simulate_shared_keystrokes(["v", "3", "l", "*"]).await;
cx.assert_shared_state("a.c. abcd ˇa.c. abcd").await;
cx.assert_shared_mode(Mode::Normal).await;
cx.simulate_shared_keystrokes("v 3 l *").await;
cx.shared_state().await.assert_eq("a.c. abcd ˇa.c. abcd");
}
#[gpui::test]
@ -663,9 +662,9 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.set_shared_state("ˇa.c. abcd a.c. abcd").await;
cx.simulate_shared_keystrokes(["d", "/", "c", "d"]).await;
cx.simulate_shared_keystrokes(["enter"]).await;
cx.assert_shared_state("ˇcd a.c. abcd").await;
cx.simulate_shared_keystrokes("d / c d").await;
cx.simulate_shared_keystrokes("enter").await;
cx.shared_state().await.assert_eq("ˇcd a.c. abcd");
}
#[gpui::test]
@ -673,24 +672,24 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.set_shared_state("ˇa.c. abcd a.c. abcd").await;
cx.simulate_shared_keystrokes(["v", "/", "c", "d"]).await;
cx.simulate_shared_keystrokes(["enter"]).await;
cx.assert_shared_state("«a.c. abcˇ»d a.c. abcd").await;
cx.simulate_shared_keystrokes("v / c d").await;
cx.simulate_shared_keystrokes("enter").await;
cx.shared_state().await.assert_eq("«a.c. abcˇ»d a.c. abcd");
cx.set_shared_state("a a aˇ a a a").await;
cx.simulate_shared_keystrokes(["v", "/", "a"]).await;
cx.simulate_shared_keystrokes(["enter"]).await;
cx.assert_shared_state("a a a« aˇ» a a").await;
cx.simulate_shared_keystrokes(["/", "enter"]).await;
cx.assert_shared_state("a a a« a aˇ» a").await;
cx.simulate_shared_keystrokes(["?", "enter"]).await;
cx.assert_shared_state("a a a« aˇ» a a").await;
cx.simulate_shared_keystrokes(["?", "enter"]).await;
cx.assert_shared_state("a a «ˇa »a a a").await;
cx.simulate_shared_keystrokes(["/", "enter"]).await;
cx.assert_shared_state("a a a« aˇ» a a").await;
cx.simulate_shared_keystrokes(["/", "enter"]).await;
cx.assert_shared_state("a a a« a aˇ» a").await;
cx.simulate_shared_keystrokes("v / a").await;
cx.simulate_shared_keystrokes("enter").await;
cx.shared_state().await.assert_eq("a a a« aˇ» a a");
cx.simulate_shared_keystrokes("/ enter").await;
cx.shared_state().await.assert_eq("a a a« a aˇ» a");
cx.simulate_shared_keystrokes("? enter").await;
cx.shared_state().await.assert_eq("a a a« aˇ» a a");
cx.simulate_shared_keystrokes("? enter").await;
cx.shared_state().await.assert_eq("a a «ˇa »a a a");
cx.simulate_shared_keystrokes("/ enter").await;
cx.shared_state().await.assert_eq("a a a« aˇ» a a");
cx.simulate_shared_keystrokes("/ enter").await;
cx.shared_state().await.assert_eq("a a a« a aˇ» a");
}
#[gpui::test]
@ -704,16 +703,14 @@ mod test {
"
})
.await;
cx.simulate_shared_keystrokes(["ctrl-v", "j", "/", "f"])
.await;
cx.simulate_shared_keystrokes(["enter"]).await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes("ctrl-v j / f").await;
cx.simulate_shared_keystrokes("enter").await;
cx.shared_state().await.assert_eq(indoc! {
"«one twoˇ»
«three »our
five six
"
})
.await;
});
}
// cargo test -p vim --features neovim test_replace_with_range
@ -732,10 +729,9 @@ mod test {
"
})
.await;
cx.simulate_shared_keystrokes([":", "2", ",", "5", "s", "/", "a", "/", "b"])
.await;
cx.simulate_shared_keystrokes(["enter"]).await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes(": 2 , 5 s / a / b").await;
cx.simulate_shared_keystrokes("enter").await;
cx.shared_state().await.assert_eq(indoc! {
"a
b
b
@ -744,7 +740,6 @@ mod test {
a
a
"
})
.await;
});
}
}

View File

@ -95,37 +95,37 @@ mod test {
// supports a single cursor
cx.set_state(indoc! {"ˇabc\n"}, Mode::Normal);
cx.simulate_keystrokes(["s", "x"]);
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.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.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.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.simulate_keystrokes("5 s x");
cx.assert_editor_state("\n");
// it handles multibyte characters
cx.set_state(indoc! {"ˇcàfé\n"}, Mode::Normal);
cx.simulate_keystrokes(["4", "s"]);
cx.simulate_keystrokes("4 s");
cx.assert_editor_state("ˇ\n");
// should transactionally undo selection changes
cx.simulate_keystrokes(["escape", "u"]);
cx.simulate_keystrokes("escape u");
cx.assert_editor_state("ˇcàfé\n");
// it handles visual line mode
@ -136,7 +136,7 @@ mod test {
gamma"},
Mode::Normal,
);
cx.simulate_keystrokes(["shift-v", "s"]);
cx.simulate_keystrokes("shift-v s");
cx.assert_editor_state(indoc! {"
alpha
ˇ
@ -148,66 +148,86 @@ mod test {
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.simulate_shared_keystrokes("v w c").await;
cx.shared_state().await.assert_eq("The quick ˇ");
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! {"
cx.simulate_shared_keystrokes("v w j c").await;
cx.shared_state().await.assert_eq(indoc! {"
The ˇver
the lazy dog"})
.await;
the lazy dog"});
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;
}
cx.simulate_at_each_offset(
"v w j c",
indoc! {"
The ˇquick brown
fox jumps ˇover
the ˇlazy dog"},
)
.await
.assert_matches();
cx.simulate_at_each_offset(
"v w k c",
indoc! {"
The ˇquick brown
fox jumps ˇover
the ˇlazy dog"},
)
.await
.assert_matches();
}
#[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! {"
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.simulate(
"shift-v c",
indoc! {"
The quˇick brown
fox jumps over
the lazy dog"})
.await;
the lazy dog"},
)
.await
.assert_matches();
// Test pasting code copied on change
cx.simulate_shared_keystrokes(["escape", "j", "p"]).await;
cx.assert_state_matches().await;
cx.simulate_shared_keystrokes("escape j p").await;
cx.shared_state().await.assert_matches();
cx.assert_all(indoc! {"
cx.simulate_at_each_offset(
"shift-v c",
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 laˇzy dog"},
)
.await
.assert_matches();
cx.simulate(
"shift-v j c",
indoc! {"
The quˇick brown
fox jumps over
the lazy dog"})
.await;
the lazy dog"},
)
.await
.assert_matches();
// Test pasting code copied on delete
cx.simulate_shared_keystrokes(["escape", "j", "p"]).await;
cx.assert_state_matches().await;
cx.simulate_shared_keystrokes("escape j p").await;
cx.shared_state().await.assert_matches();
cx.assert_all(indoc! {"
cx.simulate_at_each_offset(
"shift-v j c",
indoc! {"
The quick brown
fox juˇmps over
the laˇzy dog"})
.await;
the laˇzy dog"},
)
.await
.assert_matches();
}
#[gpui::test]
@ -222,55 +242,46 @@ mod test {
// normal mode
cx.set_shared_state(initial_state).await;
cx.simulate_shared_keystrokes(["shift-s", "o"]).await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("shift-s o").await;
cx.shared_state().await.assert_eq(indoc! {"
The quick brown
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! {"
cx.simulate_shared_keystrokes("v k shift-s o").await;
cx.shared_state().await.assert_eq(indoc! {"
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! {"
cx.simulate_shared_keystrokes("ctrl-v j shift-s o").await;
cx.shared_state().await.assert_eq(indoc! {"
The quick brown
"})
.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! {"
cx.simulate_shared_keystrokes("v $ shift-s o").await;
cx.shared_state().await.assert_eq(indoc! {"
The quick brown
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! {"
cx.simulate_shared_keystrokes("> > shift-s o").await;
cx.shared_state().await.assert_eq(indoc! {"
The quick brown
the lazy dog
"})
.await;
"});
}
}

View File

@ -962,7 +962,7 @@ mod test {
use crate::{
state::Mode,
test::{ExemptionFeatures, NeovimBackedTestContext, VimTestContext},
test::{NeovimBackedTestContext, VimTestContext},
};
const WORD_LOCATIONS: &str = indoc! {"
@ -985,28 +985,36 @@ mod 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;
cx.simulate_at_each_offset("c i w", WORD_LOCATIONS)
.await
.assert_matches();
cx.simulate_at_each_offset("c i shift-w", WORD_LOCATIONS)
.await
.assert_matches();
cx.simulate_at_each_offset("c a w", WORD_LOCATIONS)
.await
.assert_matches();
cx.simulate_at_each_offset("c a shift-w", WORD_LOCATIONS)
.await
.assert_matches();
}
#[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;
cx.simulate_at_each_offset("d i w", WORD_LOCATIONS)
.await
.assert_matches();
cx.simulate_at_each_offset("d i shift-w", WORD_LOCATIONS)
.await
.assert_matches();
cx.simulate_at_each_offset("d a w", WORD_LOCATIONS)
.await
.assert_matches();
cx.simulate_at_each_offset("d a shift-w", WORD_LOCATIONS)
.await
.assert_matches();
}
#[gpui::test]
@ -1021,160 +1029,21 @@ mod test {
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)
cx.simulate_shared_keystrokes("v").await;
cx.shared_state()
.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)
.assert_eq("The quick brown\n«\nˇ»fox");
cx.simulate_shared_keystrokes("i w").await;
cx.shared_state()
.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);
.assert_eq("The quick brown\n«\nˇ»fox");
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)
cx.simulate_at_each_offset("v i w", WORD_LOCATIONS)
.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;
}
.assert_matches();
cx.simulate_at_each_offset("v i shift-w", WORD_LOCATIONS)
.await
.assert_matches();
}
const PARAGRAPH_EXAMPLES: &[&'static str] = &[
@ -1237,10 +1106,12 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
for paragraph_example in PARAGRAPH_EXAMPLES {
cx.assert_binding_matches_all(["c", "i", "p"], paragraph_example)
.await;
cx.assert_binding_matches_all(["c", "a", "p"], paragraph_example)
.await;
cx.simulate_at_each_offset("c i p", paragraph_example)
.await
.assert_matches();
cx.simulate_at_each_offset("c a p", paragraph_example)
.await
.assert_matches();
}
}
@ -1249,60 +1120,15 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
for paragraph_example in PARAGRAPH_EXAMPLES {
cx.assert_binding_matches_all(["d", "i", "p"], paragraph_example)
.await;
cx.assert_binding_matches_all(["d", "a", "p"], paragraph_example)
.await;
cx.simulate_at_each_offset("d i p", paragraph_example)
.await
.assert_matches();
cx.simulate_at_each_offset("d a p", paragraph_example)
.await
.assert_matches();
}
}
#[gpui::test]
async fn test_paragraph_object_with_landing_positions_not_at_beginning_of_line(
cx: &mut gpui::TestAppContext,
) {
// Landing position not at the beginning of the line
const PARAGRAPH_LANDING_POSITION_EXAMPLE: &'static str = indoc! {"
The quick brown fox jumpsˇ
over the lazy dog.ˇ
ˇ ˇ\
ˇ ˇ
ˇ\ ˇ\
ˇThe quick brown fox jumpsˇ
ˇover the lazy dog.ˇ
ˇ ˇ\
ˇ
ˇ ˇ\
ˇ\ ˇ\
"};
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.assert_binding_matches_all_exempted(
["c", "i", "p"],
PARAGRAPH_LANDING_POSITION_EXAMPLE,
ExemptionFeatures::IncorrectLandingPosition,
)
.await;
cx.assert_binding_matches_all_exempted(
["c", "a", "p"],
PARAGRAPH_LANDING_POSITION_EXAMPLE,
ExemptionFeatures::IncorrectLandingPosition,
)
.await;
cx.assert_binding_matches_all_exempted(
["d", "i", "p"],
PARAGRAPH_LANDING_POSITION_EXAMPLE,
ExemptionFeatures::IncorrectLandingPosition,
)
.await;
cx.assert_binding_matches_all_exempted(
["d", "a", "p"],
PARAGRAPH_LANDING_POSITION_EXAMPLE,
ExemptionFeatures::IncorrectLandingPosition,
)
.await;
}
#[gpui::test]
async fn test_visual_paragraph_object(cx: &mut gpui::TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
@ -1332,27 +1158,24 @@ mod test {
];
for paragraph_example in EXAMPLES {
cx.assert_binding_matches_all(["v", "i", "p"], paragraph_example)
.await;
cx.assert_binding_matches_all(["v", "a", "p"], paragraph_example)
.await;
cx.simulate_at_each_offset("v i p", paragraph_example)
.await
.assert_matches();
cx.simulate_at_each_offset("v a p", paragraph_example)
.await
.assert_matches();
}
}
// 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ˇ'ˇ`ˇg"};
'ˇfox juˇmps ov`ˇer
the ˇlazy d'o`ˇg"};
const SURROUNDING_OBJECTS: &[(char, char)] = &[
('\'', '\''), // Quote
('`', '`'), // Back Quote
('"', '"'), // Double Quote
('(', ')'), // Parentheses
('[', ']'), // SquareBrackets
('{', '}'), // CurlyBrackets
('<', '>'), // AngleBrackets
('"', '"'), // Double Quote
('(', ')'), // Parentheses
];
#[gpui::test]
@ -1364,14 +1187,18 @@ mod test {
.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;
cx.simulate_at_each_offset(&format!("c i {start}"), &marked_string)
.await
.assert_matches();
cx.simulate_at_each_offset(&format!("c i {end}"), &marked_string)
.await
.assert_matches();
cx.simulate_at_each_offset(&format!("c a {start}"), &marked_string)
.await
.assert_matches();
cx.simulate_at_each_offset(&format!("c a {end}"), &marked_string)
.await
.assert_matches();
}
}
#[gpui::test]
@ -1383,53 +1210,48 @@ mod test {
"helˇlo \"world\"!"
})
.await;
cx.simulate_shared_keystrokes(["v", "i", "\""]).await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes("v i \"").await;
cx.shared_state().await.assert_eq(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! {
cx.simulate_shared_keystrokes("v i \"").await;
cx.shared_state().await.assert_eq(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! {
cx.simulate_shared_keystrokes("v a \"").await;
cx.shared_state().await.assert_eq(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! {
cx.simulate_shared_keystrokes("v a \"").await;
cx.shared_state().await.assert_eq(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! {
cx.simulate_shared_keystrokes("v a \"").await;
cx.shared_state().await.assert_eq(indoc! {
"hello «\"world\" ˇ»
goodbye"
})
.await;
});
}
#[gpui::test]
@ -1445,15 +1267,14 @@ mod test {
}"
})
.await;
cx.simulate_shared_keystrokes(["v", "i", "{"]).await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("v i {").await;
cx.shared_state().await.assert_eq(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 == \"\" {
@ -1463,15 +1284,14 @@ mod test {
}"
})
.await;
cx.simulate_shared_keystrokes(["v", "i", "{"]).await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("v i {").await;
cx.shared_state().await.assert_eq(indoc! {"
func empty(a string) bool {
if a == \"\" {
« return true
ˇ» }
return false
}"})
.await;
}"});
cx.set_shared_state(indoc! {
"func empty(a string) bool {
@ -1482,15 +1302,14 @@ mod test {
}"
})
.await;
cx.simulate_shared_keystrokes(["v", "i", "{"]).await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("v i {").await;
cx.shared_state().await.assert_eq(indoc! {"
func empty(a string) bool {
if a == \"\" {
« return true
ˇ» }
return false
}"})
.await;
}"});
}
#[gpui::test]
@ -1502,21 +1321,19 @@ mod test {
"h\"e\\\"lˇlo \\\"world\"!"
})
.await;
cx.simulate_shared_keystrokes(["v", "i", "\""]).await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes("v i \"").await;
cx.shared_state().await.assert_eq(indoc! {
"h\"«e\\\"llo \\\"worldˇ»\"!"
})
.await;
});
cx.set_shared_state(indoc! {
"hello \"teˇst \\\"inside\\\" world\""
})
.await;
cx.simulate_shared_keystrokes(["v", "i", "\""]).await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes("v i \"").await;
cx.shared_state().await.assert_eq(indoc! {
"hello \"«test \\\"inside\\\" worldˇ»\""
})
.await;
});
}
#[gpui::test]
@ -1530,7 +1347,7 @@ mod test {
},
Mode::Normal,
);
cx.simulate_keystrokes(["c", "i", "|"]);
cx.simulate_keystrokes("c i |");
cx.assert_state(
indoc! {"
fn boop() {
@ -1539,7 +1356,7 @@ mod test {
},
Mode::Insert,
);
cx.simulate_keystrokes(["escape", "1", "8", "|"]);
cx.simulate_keystrokes("escape 1 8 |");
cx.assert_state(
indoc! {"
fn boop() {
@ -1549,7 +1366,7 @@ mod test {
Mode::Normal,
);
cx.simulate_keystrokes(["v", "a", "|"]);
cx.simulate_keystrokes("v a |");
cx.assert_state(
indoc! {"
fn boop() {
@ -1566,7 +1383,7 @@ mod test {
// Generic arguments
cx.set_state("fn boop<A: ˇDebug, B>() {}", Mode::Normal);
cx.simulate_keystrokes(["v", "i", "a"]);
cx.simulate_keystrokes("v i a");
cx.assert_state("fn boop<«A: Debugˇ», B>() {}", Mode::Visual);
// Function arguments
@ -1574,11 +1391,11 @@ mod test {
"fn boop(ˇarg_a: (Tuple, Of, Types), arg_b: String) {}",
Mode::Normal,
);
cx.simulate_keystrokes(["d", "a", "a"]);
cx.simulate_keystrokes("d a a");
cx.assert_state("fn boop(ˇarg_b: String) {}", Mode::Normal);
cx.set_state("std::namespace::test(\"strinˇg\", a.b.c())", Mode::Normal);
cx.simulate_keystrokes(["v", "a", "a"]);
cx.simulate_keystrokes("v a a");
cx.assert_state("std::namespace::test(«\"string\", ˇ»a.b.c())", Mode::Visual);
// Tuple, vec, and array arguments
@ -1586,34 +1403,34 @@ mod test {
"fn boop(arg_a: (Tuple, Ofˇ, Types), arg_b: String) {}",
Mode::Normal,
);
cx.simulate_keystrokes(["c", "i", "a"]);
cx.simulate_keystrokes("c i a");
cx.assert_state(
"fn boop(arg_a: (Tuple, ˇ, Types), arg_b: String) {}",
Mode::Insert,
);
cx.set_state("let a = (test::call(), 'p', my_macro!{ˇ});", Mode::Normal);
cx.simulate_keystrokes(["c", "a", "a"]);
cx.simulate_keystrokes("c a a");
cx.assert_state("let a = (test::call(), 'p'ˇ);", Mode::Insert);
cx.set_state("let a = [test::call(ˇ), 300];", Mode::Normal);
cx.simulate_keystrokes(["c", "i", "a"]);
cx.simulate_keystrokes("c i a");
cx.assert_state("let a = [ˇ, 300];", Mode::Insert);
cx.set_state(
"let a = vec![Vec::new(), vecˇ![test::call(), 300]];",
Mode::Normal,
);
cx.simulate_keystrokes(["c", "a", "a"]);
cx.simulate_keystrokes("c a a");
cx.assert_state("let a = vec![Vec::new()ˇ];", Mode::Insert);
// Cursor immediately before / after brackets
cx.set_state("let a = [test::call(first_arg)ˇ]", Mode::Normal);
cx.simulate_keystrokes(["v", "i", "a"]);
cx.simulate_keystrokes("v i a");
cx.assert_state("let a = [«test::call(first_arg)ˇ»]", Mode::Visual);
cx.set_state("let a = [test::callˇ(first_arg)]", Mode::Normal);
cx.simulate_keystrokes(["v", "i", "a"]);
cx.simulate_keystrokes("v i a");
cx.assert_state("let a = [«test::call(first_arg)ˇ»]", Mode::Visual);
}
@ -1626,14 +1443,18 @@ mod test {
.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;
cx.simulate_at_each_offset(&format!("d i {start}"), &marked_string)
.await
.assert_matches();
cx.simulate_at_each_offset(&format!("d i {end}"), &marked_string)
.await
.assert_matches();
cx.simulate_at_each_offset(&format!("d a {start}"), &marked_string)
.await
.assert_matches();
cx.simulate_at_each_offset(&format!("d a {end}"), &marked_string)
.await
.assert_matches();
}
}
@ -1642,17 +1463,17 @@ mod test {
let mut cx = VimTestContext::new_html(cx).await;
cx.set_state("<html><head></head><body><b>hˇi!</b></body>", Mode::Normal);
cx.simulate_keystrokes(["v", "i", "t"]);
cx.simulate_keystrokes("v i t");
cx.assert_state(
"<html><head></head><body><b>«hi!ˇ»</b></body>",
Mode::Visual,
);
cx.simulate_keystrokes(["a", "t"]);
cx.simulate_keystrokes("a t");
cx.assert_state(
"<html><head></head><body>«<b>hi!</b>ˇ»</body>",
Mode::Visual,
);
cx.simulate_keystrokes(["a", "t"]);
cx.simulate_keystrokes("a t");
cx.assert_state(
"<html><head></head>«<body><b>hi!</b></body>ˇ»",
Mode::Visual,
@ -1663,12 +1484,12 @@ mod test {
"<html><head></head><body> ˇ <b>hi!</b></body>",
Mode::Normal,
);
cx.simulate_keystrokes(["v", "i", "t"]);
cx.simulate_keystrokes("v i t");
cx.assert_state(
"<html><head></head><body> <b>«hi!ˇ»</b></body>",
Mode::Visual,
);
cx.simulate_keystrokes(["a", "t"]);
cx.simulate_keystrokes("a t");
cx.assert_state(
"<html><head></head><body> «<b>hi!</b>ˇ»</body>",
Mode::Visual,
@ -1679,12 +1500,12 @@ mod test {
"<html><head></head><body><bˇ>hi!</b><b>hello!</b></body>",
Mode::Normal,
);
cx.simulate_keystrokes(["v", "a", "t"]);
cx.simulate_keystrokes("v a t");
cx.assert_state(
"<html><head></head><body>«<b>hi!</b>ˇ»<b>hello!</b></body>",
Mode::Visual,
);
cx.simulate_keystrokes(["i", "t"]);
cx.simulate_keystrokes("i t");
cx.assert_state(
"<html><head></head><body>«<b>hi!</b><b>hello!</b>ˇ»</body>",
Mode::Visual,
@ -1695,12 +1516,12 @@ mod test {
"<html><head></head><body><«b>hi!ˇ»</b></body>",
Mode::Visual,
);
cx.simulate_keystrokes(["i", "t"]);
cx.simulate_keystrokes("i t");
cx.assert_state(
"<html><head></head><body><b>«hi!ˇ»</b></body>",
Mode::Visual,
);
cx.simulate_keystrokes(["a", "t"]);
cx.simulate_keystrokes("a t");
cx.assert_state(
"<html><head></head><body>«<b>hi!</b>ˇ»</body>",
Mode::Visual,
@ -1710,7 +1531,7 @@ mod test {
"<html><head></head><body><«b>hi!</ˇ»b></body>",
Mode::Visual,
);
cx.simulate_keystrokes(["a", "t"]);
cx.simulate_keystrokes("a t");
cx.assert_state(
"<html><head></head>«<body><b>hi!</b></body>ˇ»",
Mode::Visual,

View File

@ -148,9 +148,9 @@ mod test {
#[gpui::test]
async fn test_enter_and_exit_replace_mode(cx: &mut gpui::TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
cx.simulate_keystroke("shift-r");
cx.simulate_keystrokes("shift-r");
assert_eq!(cx.mode(), Mode::Replace);
cx.simulate_keystroke("escape");
cx.simulate_keystrokes("escape");
assert_eq!(cx.mode(), Mode::Normal);
}
@ -164,14 +164,11 @@ mod test {
fox jumps over
the lazy dog."})
.await;
cx.simulate_shared_keystrokes(["shift-r", "O", "n", "e"])
.await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("shift-r O n e").await;
cx.shared_state().await.assert_eq(indoc! {"
Oneˇ quick brown
fox jumps over
the lazy dog."})
.await;
assert_eq!(Mode::Replace, cx.neovim_mode().await);
the lazy dog."});
// test replace with line ending
cx.set_shared_state(indoc! {"
@ -179,13 +176,11 @@ mod test {
fox jumps over
the lazy dog."})
.await;
cx.simulate_shared_keystrokes(["shift-r", "O", "n", "e"])
.await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("shift-r O n e").await;
cx.shared_state().await.assert_eq(indoc! {"
The quick browOneˇ
fox jumps over
the lazy dog."})
.await;
the lazy dog."});
// test replace with blank line
cx.set_shared_state(indoc! {"
@ -194,28 +189,12 @@ mod test {
fox jumps over
the lazy dog."})
.await;
cx.simulate_shared_keystrokes(["shift-r", "O", "n", "e"])
.await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("shift-r O n e").await;
cx.shared_state().await.assert_eq(indoc! {"
The quick brown
Oneˇ
fox jumps over
the lazy dog."})
.await;
// test replace with multi cursor
cx.set_shared_state(indoc! {"
ˇThe quick brown
fox jumps over
the lazy ˇdog."})
.await;
cx.simulate_shared_keystrokes(["shift-r", "O", "n", "e"])
.await;
cx.assert_shared_state(indoc! {"
Oneˇ quick brown
fox jumps over
the lazy Oneˇ."})
.await;
the lazy dog."});
// test replace with newline
cx.set_shared_state(indoc! {"
@ -223,37 +202,39 @@ mod test {
fox jumps over
the lazy dog."})
.await;
cx.simulate_shared_keystrokes(["shift-r", "enter", "O", "n", "e"])
.await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("shift-r enter O n e").await;
cx.shared_state().await.assert_eq(indoc! {"
The qu
Oneˇ brown
fox jumps over
the lazy dog."})
.await;
the lazy dog."});
// test replace with multi cursor and newline
cx.set_shared_state(indoc! {"
cx.set_state(
indoc! {"
ˇThe quick brown
fox jumps over
the lazy ˇdog."})
.await;
cx.simulate_shared_keystrokes(["shift-r", "O", "n", "e"])
.await;
cx.assert_shared_state(indoc! {"
the lazy ˇdog."},
Mode::Normal,
);
cx.simulate_keystrokes("shift-r O n e");
cx.assert_state(
indoc! {"
Oneˇ quick brown
fox jumps over
the lazy Oneˇ."})
.await;
cx.simulate_shared_keystrokes(["enter", "T", "w", "o"])
.await;
cx.assert_shared_state(indoc! {"
the lazy Oneˇ."},
Mode::Replace,
);
cx.simulate_keystrokes("enter T w o");
cx.assert_state(
indoc! {"
One
Twoˇck brown
fox jumps over
the lazy One
Twoˇ"})
.await;
Twoˇ"},
Mode::Replace,
);
}
#[gpui::test]
@ -276,60 +257,23 @@ mod test {
fox jumps over
the lazy dog."
},
// replace undo with multi cursor
indoc! {"
The quick browˇn
fox jumps over
the lazy ˇdog."
},
];
for example in UNDO_REPLACE_EXAMPLES {
// normal undo
cx.assert_binding_matches(
[
"shift-r",
"O",
"n",
"e",
"backspace",
"backspace",
"backspace",
],
example,
)
.await;
cx.simulate("shift-r O n e backspace backspace backspace", example)
.await
.assert_matches();
// undo with new line
cx.assert_binding_matches(
[
"shift-r",
"O",
"enter",
"e",
"backspace",
"backspace",
"backspace",
],
cx.simulate("shift-r O enter e backspace backspace backspace", example)
.await
.assert_matches();
cx.simulate(
"shift-r O enter n enter e backspace backspace backspace backspace backspace",
example,
)
.await;
cx.assert_binding_matches(
[
"shift-r",
"O",
"enter",
"n",
"enter",
"e",
"backspace",
"backspace",
"backspace",
"backspace",
"backspace",
],
example,
)
.await;
.await
.assert_matches();
}
}
@ -337,16 +281,10 @@ mod test {
async fn test_replace_multicursor(cx: &mut gpui::TestAppContext) {
let mut cx = VimTestContext::new(cx, true).await;
cx.set_state("ˇabcˇabcabc", Mode::Normal);
cx.simulate_keystrokes(["shift-r", "1", "2", "3", "4"]);
cx.simulate_keystrokes("shift-r 1 2 3 4");
cx.assert_state("1234ˇ234ˇbc", Mode::Replace);
assert_eq!(cx.mode(), Mode::Replace);
cx.simulate_keystrokes([
"backspace",
"backspace",
"backspace",
"backspace",
"backspace",
]);
cx.simulate_keystrokes("backspace backspace backspace backspace backspace");
cx.assert_state("ˇabˇcabcabc", Mode::Replace);
}
@ -355,7 +293,7 @@ mod test {
let mut cx = VimTestContext::new(cx, true).await;
cx.set_state("ˇaaaa", Mode::Normal);
cx.simulate_keystrokes(["0", "shift-r", "b", "b", "b", "escape", "u"]);
cx.simulate_keystrokes("0 shift-r b b b escape u");
cx.assert_state("ˇaaaa", Mode::Normal);
}
}

View File

@ -527,7 +527,7 @@ mod test {
the lazy dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["y", "s", "i", "w", "{"]);
cx.simulate_keystrokes("y s i w {");
cx.assert_state(
indoc! {"
The ˇ{ quick } brown
@ -544,7 +544,7 @@ mod test {
the lazy dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["y", "s", "i", "w", "}"]);
cx.simulate_keystrokes("y s i w }");
cx.assert_state(
indoc! {"
The ˇ{quick} brown
@ -561,7 +561,7 @@ mod test {
the lazy dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["y", "s", "$", "}"]);
cx.simulate_keystrokes("y s $ }");
cx.assert_state(
indoc! {"
The quˇ{ick brown}
@ -578,7 +578,7 @@ mod test {
the laˇzy dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["y", "s", "i", "w", "'"]);
cx.simulate_keystrokes("y s i w '");
cx.assert_state(
indoc! {"
The ˇ'quick' brown
@ -595,7 +595,7 @@ mod test {
the laˇzy dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["y", "s", "$", "'"]);
cx.simulate_keystrokes("y s $ '");
cx.assert_state(
indoc! {"
The quˇ'ick brown'
@ -612,7 +612,7 @@ mod test {
the laˇzy dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["y", "s", "$", "1"]);
cx.simulate_keystrokes("y s $ 1");
cx.assert_state(
indoc! {"
The quˇ1ick brown1
@ -629,7 +629,7 @@ mod test {
the lazy dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["y", "s", "s", "{"]);
cx.simulate_keystrokes("y s s {");
cx.assert_state(
indoc! {"
ˇ{ The quick brown }
@ -645,7 +645,7 @@ mod test {
the lazy dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["y", "s", "s", "{"]);
cx.simulate_keystrokes("y s s {");
cx.assert_state(
indoc! {"
ˇ{ The quick brown }
@ -653,7 +653,7 @@ mod test {
the lazy dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["2", "y", "s", "s", ")"]);
cx.simulate_keystrokes("2 y s s )");
cx.assert_state(
indoc! {"
ˇ({ The quick brown }
@ -675,7 +675,7 @@ mod test {
the lazy dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["d", "s", "{"]);
cx.simulate_keystrokes("d s {");
cx.assert_state(
indoc! {"
The ˇquick brown
@ -692,7 +692,7 @@ mod test {
the lazy dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["d", "s", "["]);
cx.simulate_keystrokes("d s [");
cx.assert_state(
indoc! {"
The {quˇick} brown
@ -710,7 +710,7 @@ mod test {
the lazy dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["d", "s", "{"]);
cx.simulate_keystrokes("d s {");
cx.assert_state(
indoc! {"
The {quick} brˇown
@ -727,7 +727,7 @@ mod test {
the lazy dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["d", "s", "{"]);
cx.simulate_keystrokes("d s {");
cx.assert_state(
indoc! {"
The ˇquick brown
@ -744,7 +744,7 @@ mod test {
the [laˇzy] dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["d", "s", "]"]);
cx.simulate_keystrokes("d s ]");
cx.assert_state(
indoc! {"
The ˇquick brown
@ -761,7 +761,7 @@ mod test {
the [laˇzy] dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["d", "s", "["]);
cx.simulate_keystrokes("d s [");
cx.assert_state(
indoc! {"
The ˇquick brown
@ -777,7 +777,7 @@ mod test {
the [laˇzy ] dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["d", "s", "["]);
cx.simulate_keystrokes("d s [");
cx.assert_state(
indoc! {"
The ˇquick brown
@ -796,7 +796,7 @@ mod test {
the {laˇzy} dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["d", "s", "{"]);
cx.simulate_keystrokes("d s {");
cx.assert_state(
indoc! {"
The [quick] brown
@ -815,7 +815,7 @@ mod test {
}"},
Mode::Normal,
);
cx.simulate_keystrokes(["d", "s", "}"]);
cx.simulate_keystrokes("d s }");
cx.assert_state(
indoc! {"
fn test_surround() ˇ
@ -838,7 +838,7 @@ mod test {
the lazy dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["c", "s", "{", "["]);
cx.simulate_keystrokes("c s { [");
cx.assert_state(
indoc! {"
The ˇ[ quick ] brown
@ -855,7 +855,7 @@ mod test {
the {laˇzy} dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["c", "s", "{", "["]);
cx.simulate_keystrokes("c s { [");
cx.assert_state(
indoc! {"
The ˇ[ quick ] brown
@ -872,7 +872,7 @@ mod test {
the {laˇzy} dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["c", "s", "{", "["]);
cx.simulate_keystrokes("c s { [");
cx.assert_state(
indoc! {"
The ˇ[ quick ] brown
@ -889,7 +889,7 @@ mod test {
the {laˇzy} dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["c", "s", "{", "]"]);
cx.simulate_keystrokes("c s { ]");
cx.assert_state(
indoc! {"
The ˇ[quick] brown
@ -906,7 +906,7 @@ mod test {
the [laˇzy] dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["c", "s", "[", "'"]);
cx.simulate_keystrokes("c s [ '");
cx.assert_state(
indoc! {"
The {quick} brown
@ -925,7 +925,7 @@ mod test {
};"},
Mode::Normal,
);
cx.simulate_keystrokes(["c", "s", "{", "["]);
cx.simulate_keystrokes("c s { [");
cx.assert_state(
indoc! {"
fn test_surround() ˇ[
@ -948,7 +948,7 @@ mod test {
the lazy dog."},
Mode::Normal,
);
cx.simulate_keystrokes(["y", "s", "i", "w", "["]);
cx.simulate_keystrokes("y s i w [");
cx.assert_state(
indoc! {"
The ˇ[ quick ] brown
@ -957,7 +957,7 @@ mod test {
Mode::Normal,
);
cx.simulate_keystrokes(["c", "s", "[", "}"]);
cx.simulate_keystrokes("c s [ }");
cx.assert_state(
indoc! {"
The ˇ{quick} brown
@ -966,7 +966,7 @@ mod test {
Mode::Normal,
);
cx.simulate_keystrokes(["d", "s", "{"]);
cx.simulate_keystrokes("d s {");
cx.assert_state(
indoc! {"
The ˇquick brown
@ -975,7 +975,7 @@ mod test {
Mode::Normal,
);
cx.simulate_keystrokes(["u"]);
cx.simulate_keystrokes("u");
cx.assert_state(
indoc! {"
The ˇ{quick} brown

File diff suppressed because it is too large Load Diff

View File

@ -1,92 +0,0 @@
use std::ops::{Deref, DerefMut};
use crate::state::Mode;
use super::{ExemptionFeatures, NeovimBackedTestContext, SUPPORTED_FEATURES};
pub struct NeovimBackedBindingTestContext<const COUNT: usize> {
cx: NeovimBackedTestContext,
keystrokes_under_test: [&'static str; COUNT],
}
impl<const COUNT: usize> NeovimBackedBindingTestContext<COUNT> {
pub fn new(keystrokes_under_test: [&'static str; COUNT], cx: NeovimBackedTestContext) -> Self {
Self {
cx,
keystrokes_under_test,
}
}
pub fn consume(self) -> NeovimBackedTestContext {
self.cx
}
pub fn binding<const NEW_COUNT: usize>(
self,
keystrokes: [&'static str; NEW_COUNT],
) -> NeovimBackedBindingTestContext<NEW_COUNT> {
self.consume().binding(keystrokes)
}
pub async fn assert(&mut self, marked_positions: &str) {
self.cx
.assert_binding_matches(self.keystrokes_under_test, marked_positions)
.await;
}
pub async fn assert_exempted(&mut self, marked_positions: &str, feature: ExemptionFeatures) {
if SUPPORTED_FEATURES.contains(&feature) {
self.cx
.assert_binding_matches(self.keystrokes_under_test, marked_positions)
.await
}
}
pub fn assert_manual(
&mut self,
initial_state: &str,
mode_before: Mode,
state_after: &str,
mode_after: Mode,
) {
self.cx.assert_binding(
self.keystrokes_under_test,
initial_state,
mode_before,
state_after,
mode_after,
);
}
pub async fn assert_all(&mut self, marked_positions: &str) {
self.cx
.assert_binding_matches_all(self.keystrokes_under_test, marked_positions)
.await
}
pub async fn assert_all_exempted(
&mut self,
marked_positions: &str,
feature: ExemptionFeatures,
) {
if SUPPORTED_FEATURES.contains(&feature) {
self.cx
.assert_binding_matches_all(self.keystrokes_under_test, marked_positions)
.await
}
}
}
impl<const COUNT: usize> Deref for NeovimBackedBindingTestContext<COUNT> {
type Target = NeovimBackedTestContext;
fn deref(&self) -> &Self::Target {
&self.cx
}
}
impl<const COUNT: usize> DerefMut for NeovimBackedBindingTestContext<COUNT> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.cx
}
}

View File

@ -1,4 +1,3 @@
use editor::test::editor_test_context::ContextHandle;
use gpui::{px, size, BorrowAppContext, Context};
use indoc::indoc;
use settings::SettingsStore;
@ -7,57 +6,132 @@ use std::{
panic, thread,
};
use collections::{HashMap, HashSet};
use language::language_settings::{AllLanguageSettings, SoftWrap};
use util::test::marked_text_offsets;
use super::{neovim_connection::NeovimConnection, NeovimBackedBindingTestContext, VimTestContext};
use super::{neovim_connection::NeovimConnection, VimTestContext};
use crate::state::Mode;
pub const SUPPORTED_FEATURES: &[ExemptionFeatures] = &[];
/// Enum representing features we have tests for but which don't work, yet. Used
/// to add exemptions and automatically
#[derive(PartialEq, Eq)]
pub enum ExemptionFeatures {
// MOTIONS
// When an operator completes at the end of the file, an extra newline is left
OperatorLastNewlineRemains,
// OBJECTS
// Resulting position after the operation is slightly incorrect for unintuitive reasons.
IncorrectLandingPosition,
// Operator around the text object at the end of the line doesn't remove whitespace.
AroundObjectLeavesWhitespaceAtEndOfLine,
// Sentence object on empty lines
SentenceOnEmptyLines,
// Whitespace isn't included with text objects at the start of the line
SentenceAtStartOfLineWithWhitespace,
// Whitespace around sentences is slightly incorrect when starting between sentences
AroundSentenceStartingBetweenIncludesWrongWhitespace,
// Non empty selection with text objects in visual mode
NonEmptyVisualTextObjects,
// Sentence Doesn't backtrack when its at the end of the file
SentenceAfterPunctuationAtEndOfFile,
}
impl ExemptionFeatures {
pub fn supported(&self) -> bool {
SUPPORTED_FEATURES.contains(self)
}
}
pub struct NeovimBackedTestContext {
cx: VimTestContext,
// Lookup for exempted assertions. Keyed by the insertion text, and with a value indicating which
// bindings are exempted. If None, all bindings are ignored for that insertion text.
exemptions: HashMap<String, Option<HashSet<String>>>,
pub(crate) neovim: NeovimConnection,
last_set_state: Option<String>,
recent_keystrokes: Vec<String>,
}
is_dirty: bool,
#[derive(Default)]
pub struct SharedState {
neovim: String,
editor: String,
initial: String,
neovim_mode: Mode,
editor_mode: Mode,
recent_keystrokes: String,
}
impl SharedState {
#[track_caller]
pub fn assert_matches(&self) {
if self.neovim != self.editor || self.neovim_mode != self.editor_mode {
panic!(
indoc! {"Test failed (zed does not match nvim behaviour)
# initial state:
{}
# keystrokes:
{}
# neovim ({}):
{}
# zed ({}):
{}"},
self.initial,
self.recent_keystrokes,
self.neovim_mode,
self.neovim,
self.editor_mode,
self.editor,
)
}
}
#[track_caller]
pub fn assert_eq(&mut self, marked_text: &str) {
let marked_text = marked_text.replace('•', " ");
if self.neovim == marked_text
&& self.neovim == self.editor
&& self.neovim_mode == self.editor_mode
{
return;
}
let message = if self.neovim != marked_text {
"Test is incorrect (currently expected != neovim_state)"
} else {
"Editor does not match nvim behaviour"
};
panic!(
indoc! {"{}
# initial state:
{}
# keystrokes:
{}
# currently expected:
{}
# neovim ({}):
{}
# zed ({}):
{}"},
message,
self.initial,
self.recent_keystrokes,
marked_text.replace(" \n", "\n"),
self.neovim_mode,
self.neovim.replace(" \n", "\n"),
self.editor_mode,
self.editor.replace(" \n", "\n"),
)
}
}
pub struct SharedClipboard {
neovim: String,
editor: String,
state: SharedState,
}
impl SharedClipboard {
#[track_caller]
pub fn assert_eq(&self, expected: &str) {
if expected == self.neovim && self.neovim == self.editor {
return;
}
let message = if expected == self.neovim {
"Test is incorrect (currently expected != neovim_state)"
} else {
"Editor does not match nvim behaviour"
};
panic!(
indoc! {"{}
# initial state:
{}
# keystrokes:
{}
# currently expected:
{}
# neovim clipboard:
{}
# zed clipboard:
{}"},
message,
self.state.initial,
self.state.recent_keystrokes,
expected,
self.neovim,
self.editor
)
}
}
impl NeovimBackedTestContext {
@ -78,49 +152,13 @@ impl NeovimBackedTestContext {
.to_string();
Self {
cx: VimTestContext::new(cx, true).await,
exemptions: Default::default(),
neovim: NeovimConnection::new(test_name).await,
last_set_state: None,
recent_keystrokes: Default::default(),
is_dirty: false,
}
}
pub fn add_initial_state_exemptions(
&mut self,
marked_positions: &str,
missing_feature: ExemptionFeatures, // Feature required to support this exempted test case
) {
if !missing_feature.supported() {
let (unmarked_text, cursor_offsets) = marked_text_offsets(marked_positions);
for cursor_offset in cursor_offsets.iter() {
let mut marked_text = unmarked_text.clone();
marked_text.insert(*cursor_offset, 'ˇ');
// None represents all key bindings being exempted for that initial state
self.exemptions.insert(marked_text, None);
}
}
}
pub async fn simulate_shared_keystroke(&mut self, keystroke_text: &str) -> ContextHandle {
self.neovim.send_keystroke(keystroke_text).await;
self.simulate_keystroke(keystroke_text)
}
pub async fn simulate_shared_keystrokes<const COUNT: usize>(
&mut self,
keystroke_texts: [&str; COUNT],
) {
for keystroke_text in keystroke_texts.into_iter() {
self.recent_keystrokes.push(keystroke_text.to_string());
self.neovim.send_keystroke(keystroke_text).await;
}
self.simulate_keystrokes(keystroke_texts);
}
pub async fn set_shared_state(&mut self, marked_text: &str) {
let mode = if marked_text.contains('»') {
Mode::Visual
@ -131,7 +169,21 @@ impl NeovimBackedTestContext {
self.last_set_state = Some(marked_text.to_string());
self.recent_keystrokes = Vec::new();
self.neovim.set_state(marked_text).await;
self.is_dirty = true;
}
pub async fn simulate_shared_keystrokes(&mut self, keystroke_texts: &str) {
for keystroke_text in keystroke_texts.split(' ') {
self.recent_keystrokes.push(keystroke_text.to_string());
self.neovim.send_keystroke(keystroke_text).await;
}
self.simulate_keystrokes(keystroke_texts);
}
#[must_use]
pub async fn simulate(&mut self, keystrokes: &str, initial_state: &str) -> SharedState {
self.set_shared_state(initial_state).await;
self.simulate_shared_keystrokes(keystrokes).await;
self.shared_state().await
}
pub async fn set_shared_wrap(&mut self, columns: u32) {
@ -186,241 +238,51 @@ impl NeovimBackedTestContext {
self.neovim.set_option(option).await;
}
pub async fn assert_shared_state(&mut self, marked_text: &str) {
self.is_dirty = false;
let marked_text = marked_text.replace('•', " ");
let neovim = self.neovim_state().await;
let neovim_mode = self.neovim_mode().await;
let editor = self.editor_state();
let editor_mode = self.mode();
if neovim == marked_text && neovim == editor && neovim_mode == editor_mode {
return;
}
let initial_state = self
.last_set_state
.as_ref()
.unwrap_or(&"N/A".to_string())
.clone();
let message = if neovim != marked_text {
"Test is incorrect (currently expected != neovim_state)"
} else {
"Editor does not match nvim behaviour"
};
panic!(
indoc! {"{}
# initial state:
{}
# keystrokes:
{}
# currently expected:
{}
# neovim ({}):
{}
# zed ({}):
{}"},
message,
initial_state,
self.recent_keystrokes.join(" "),
marked_text.replace(" \n", "\n"),
neovim_mode,
neovim.replace(" \n", "\n"),
editor_mode,
editor.replace(" \n", "\n"),
)
}
pub async fn assert_shared_clipboard(&mut self, text: &str) {
let neovim = self.neovim.read_register('"').await;
let editor = self.read_from_clipboard().unwrap().text().clone();
if text == neovim && text == editor {
return;
}
let message = if neovim != text {
"Test is incorrect (currently expected != neovim)"
} else {
"Editor does not match nvim behaviour"
};
let initial_state = self
.last_set_state
.as_ref()
.unwrap_or(&"N/A".to_string())
.clone();
panic!(
indoc! {"{}
# initial state:
{}
# keystrokes:
{}
# currently expected:
{}
# neovim clipboard:
{}
# zed clipboard:
{}"},
message,
initial_state,
self.recent_keystrokes.join(" "),
text,
neovim,
editor
)
}
pub async fn neovim_state(&mut self) -> String {
self.neovim.marked_text().await
}
pub async fn neovim_mode(&mut self) -> Mode {
self.neovim.mode().await.unwrap()
}
pub async fn assert_shared_mode(&mut self, mode: Mode) {
let neovim = self.neovim_mode().await;
let editor = self.cx.mode();
if neovim != mode || editor != mode {
panic!(
indoc! {"Test failed (zed does not match nvim behaviour)
# desired mode:
{:?}
# neovim mode:
{:?}
# zed mode:
{:?}"},
mode, neovim, editor,
)
#[must_use]
pub async fn shared_clipboard(&mut self) -> SharedClipboard {
SharedClipboard {
state: self.shared_state().await,
neovim: self.neovim.read_register('"').await,
editor: self.read_from_clipboard().unwrap().text().clone(),
}
}
pub async fn assert_state_matches(&mut self) {
self.is_dirty = false;
let neovim = self.neovim_state().await;
let neovim_mode = self.neovim_mode().await;
let editor = self.editor_state();
let editor_mode = self.mode();
let initial_state = self
.last_set_state
.as_ref()
.unwrap_or(&"N/A".to_string())
.clone();
if neovim != editor || neovim_mode != editor_mode {
panic!(
indoc! {"Test failed (zed does not match nvim behaviour)
# initial state:
{}
# keystrokes:
{}
# neovim ({}):
{}
# zed ({}):
{}"},
initial_state,
self.recent_keystrokes.join(" "),
neovim_mode,
neovim,
editor_mode,
editor,
)
#[must_use]
pub async fn shared_state(&mut self) -> SharedState {
let (mode, marked_text) = self.neovim.state().await;
SharedState {
neovim: marked_text,
neovim_mode: mode,
editor: self.editor_state(),
editor_mode: self.mode(),
initial: self
.last_set_state
.as_ref()
.cloned()
.unwrap_or("N/A".to_string()),
recent_keystrokes: self.recent_keystrokes.join(" "),
}
}
pub async fn assert_binding_matches<const COUNT: usize>(
#[must_use]
pub async fn simulate_at_each_offset(
&mut self,
keystrokes: [&str; COUNT],
initial_state: &str,
) {
if let Some(possible_exempted_keystrokes) = self.exemptions.get(initial_state) {
match possible_exempted_keystrokes {
Some(exempted_keystrokes) => {
if exempted_keystrokes.contains(&format!("{keystrokes:?}")) {
// This keystroke was exempted for this insertion text
return;
}
}
None => {
// All keystrokes for this insertion text are exempted
return;
}
keystrokes: &str,
marked_positions: &str,
) -> SharedState {
let (unmarked_text, cursor_offsets) = marked_text_offsets(marked_positions);
for cursor_offset in cursor_offsets.iter() {
let mut marked_text = unmarked_text.clone();
marked_text.insert(*cursor_offset, 'ˇ');
let state = self.simulate(keystrokes, &marked_text).await;
if state.neovim != state.editor || state.neovim_mode != state.editor_mode {
return state;
}
}
let _state_context = self.set_shared_state(initial_state).await;
let _keystroke_context = self.simulate_shared_keystrokes(keystrokes).await;
self.assert_state_matches().await;
}
pub async fn assert_binding_matches_all<const COUNT: usize>(
&mut self,
keystrokes: [&str; COUNT],
marked_positions: &str,
) {
let (unmarked_text, cursor_offsets) = marked_text_offsets(marked_positions);
for cursor_offset in cursor_offsets.iter() {
let mut marked_text = unmarked_text.clone();
marked_text.insert(*cursor_offset, 'ˇ');
self.assert_binding_matches(keystrokes, &marked_text).await;
}
}
pub fn each_marked_position(&self, marked_positions: &str) -> Vec<String> {
let (unmarked_text, cursor_offsets) = marked_text_offsets(marked_positions);
let mut ret = Vec::with_capacity(cursor_offsets.len());
for cursor_offset in cursor_offsets.iter() {
let mut marked_text = unmarked_text.clone();
marked_text.insert(*cursor_offset, 'ˇ');
ret.push(marked_text)
}
ret
}
pub async fn assert_neovim_compatible<const COUNT: usize>(
&mut self,
marked_positions: &str,
keystrokes: [&str; COUNT],
) {
self.set_shared_state(&marked_positions).await;
self.simulate_shared_keystrokes(keystrokes).await;
self.assert_state_matches().await;
}
pub async fn assert_matches_neovim<const COUNT: usize>(
&mut self,
marked_positions: &str,
keystrokes: [&str; COUNT],
result: &str,
) {
self.set_shared_state(marked_positions).await;
self.simulate_shared_keystrokes(keystrokes).await;
self.assert_shared_state(result).await;
}
pub async fn assert_binding_matches_all_exempted<const COUNT: usize>(
&mut self,
keystrokes: [&str; COUNT],
marked_positions: &str,
feature: ExemptionFeatures,
) {
if SUPPORTED_FEATURES.contains(&feature) {
self.assert_binding_matches_all(keystrokes, marked_positions)
.await
}
}
pub fn binding<const COUNT: usize>(
self,
keystrokes: [&'static str; COUNT],
) -> NeovimBackedBindingTestContext<COUNT> {
NeovimBackedBindingTestContext::new(keystrokes, self)
SharedState::default()
}
}
@ -438,17 +300,6 @@ impl DerefMut for NeovimBackedTestContext {
}
}
// a common mistake in tests is to call set_shared_state when
// you mean asswert_shared_state. This notices that and lets
// you know.
impl Drop for NeovimBackedTestContext {
fn drop(&mut self) {
if self.is_dirty {
panic!("Test context was dropped after set_shared_state before assert_shared_state")
}
}
}
#[cfg(test)]
mod test {
use crate::test::NeovimBackedTestContext;
@ -457,8 +308,8 @@ mod test {
#[gpui::test]
async fn neovim_backed_test_context_works(cx: &mut TestAppContext) {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.assert_state_matches().await;
cx.shared_state().await.assert_matches();
cx.set_shared_state("This is a tesˇt").await;
cx.assert_state_matches().await;
cx.shared_state().await.assert_matches();
}
}

View File

@ -40,7 +40,7 @@ static NEOVIM_LOCK: ReentrantMutex<()> = ReentrantMutex::new(());
pub enum NeovimData {
Put { state: String },
Key(String),
Get { state: String, mode: Option<Mode> },
Get { state: String, mode: Mode },
ReadRegister { name: char, value: String },
Exec { command: String },
SetOption { value: String },
@ -218,7 +218,7 @@ impl NeovimConnection {
}
if let Some(NeovimData::Get { mode, state }) = self.data.back() {
if *mode == Some(Mode::Normal) && *state == marked_text {
if *mode == Mode::Normal && *state == marked_text {
return;
}
}
@ -230,7 +230,7 @@ impl NeovimConnection {
#[cfg(not(feature = "neovim"))]
pub async fn set_state(&mut self, marked_text: &str) {
if let Some(NeovimData::Get { mode, state: text }) = self.data.front() {
if *mode == Some(Mode::Normal) && *text == marked_text {
if *mode == Mode::Normal && *text == marked_text {
return;
}
self.data.pop_front();
@ -334,7 +334,7 @@ impl NeovimConnection {
}
#[cfg(feature = "neovim")]
pub async fn state(&mut self) -> (Option<Mode>, String) {
pub async fn state(&mut self) -> (Mode, String) {
let nvim_buffer = self
.nvim
.get_current_buf()
@ -369,12 +369,13 @@ impl NeovimConnection {
.expect("Could not find mode value");
let mode = match nvim_mode_text.as_ref() {
"i" => Some(Mode::Insert),
"n" => Some(Mode::Normal),
"v" => Some(Mode::Visual),
"V" => Some(Mode::VisualLine),
"\x16" => Some(Mode::VisualBlock),
_ => None,
"i" => Mode::Insert,
"n" => Mode::Normal,
"v" => Mode::Visual,
"V" => Mode::VisualLine,
"R" => Mode::Replace,
"\x16" => Mode::VisualBlock,
_ => panic!("unexpected vim mode: {nvim_mode_text}"),
};
let mut selections = Vec::new();
@ -382,7 +383,7 @@ impl NeovimConnection {
// Zed uses the index of the positions between the characters, so we need
// to add one to the end in visual mode.
match mode {
Some(Mode::VisualBlock) if selection_row != cursor_row => {
Mode::VisualBlock if selection_row != cursor_row => {
// in zed we fake a block selection by using multiple cursors (one per line)
// this code emulates that.
// to deal with casees where the selection is not perfectly rectangular we extract
@ -415,7 +416,7 @@ impl NeovimConnection {
}
}
}
Some(Mode::Visual) | Some(Mode::VisualLine) | Some(Mode::VisualBlock) => {
Mode::Visual | Mode::VisualLine | Mode::VisualBlock => {
if (selection_row, selection_col) > (cursor_row, cursor_col) {
let selection_line_length =
self.read_position("echo strlen(getline(line('v')))").await;
@ -439,7 +440,7 @@ impl NeovimConnection {
Point::new(selection_row, selection_col)..Point::new(cursor_row, cursor_col),
)
}
Some(Mode::Insert) | Some(Mode::Normal) | Some(Mode::Replace) | None => selections
Mode::Insert | Mode::Normal | Mode::Replace => selections
.push(Point::new(selection_row, selection_col)..Point::new(cursor_row, cursor_col)),
}
@ -457,7 +458,7 @@ impl NeovimConnection {
}
#[cfg(not(feature = "neovim"))]
pub async fn state(&mut self) -> (Option<Mode>, String) {
pub async fn state(&mut self) -> (Mode, String) {
if let Some(NeovimData::Get { state: raw, mode }) = self.data.front() {
(*mode, raw.to_string())
} else {
@ -465,14 +466,6 @@ impl NeovimConnection {
}
}
pub async fn mode(&mut self) -> Option<Mode> {
self.state().await.0
}
pub async fn marked_text(&mut self) -> String {
self.state().await.1
}
fn test_data_path(test_case_id: &str) -> PathBuf {
let mut data_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
data_path.push("test_data");

View File

@ -145,9 +145,9 @@ impl VimTestContext {
assert_eq!(self.mode(), mode, "{}", self.assertion_context());
}
pub fn assert_binding<const COUNT: usize>(
pub fn assert_binding(
&mut self,
keystrokes: [&str; COUNT],
keystrokes: &str,
initial_state: &str,
initial_mode: Mode,
state_after: &str,
@ -160,9 +160,9 @@ impl VimTestContext {
assert_eq!(self.active_operator(), None, "{}", self.assertion_context());
}
pub fn assert_binding_normal<const COUNT: usize>(
pub fn assert_binding_normal(
&mut self,
keystrokes: [&str; COUNT],
keystrokes: &str,
initial_state: &str,
state_after: &str,
) {

View File

@ -597,33 +597,32 @@ mod test {
// entering visual mode should select the character
// under cursor
cx.simulate_shared_keystrokes(["v"]).await;
cx.assert_shared_state(indoc! { "The «qˇ»uick brown
cx.simulate_shared_keystrokes("v").await;
cx.shared_state()
.await
.assert_eq(indoc! { "The «qˇ»uick brown
fox jumps over
the lazy dog"})
.await;
the lazy dog"});
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
cx.simulate_shared_keystrokes("w j").await;
cx.shared_state().await.assert_eq(indoc! { "The «quick brown
fox jumps »ver
the lazy dog"})
.await;
the lazy dog"});
cx.simulate_shared_keystrokes(["escape"]).await;
assert_eq!(Mode::Normal, cx.neovim_mode().await);
cx.assert_shared_state(indoc! { "The quick brown
cx.simulate_shared_keystrokes("escape").await;
cx.shared_state().await.assert_eq(indoc! { "The quick brown
fox jumps ˇover
the lazy dog"})
.await;
the lazy dog"});
// motions work backwards
cx.simulate_shared_keystrokes(["v", "k", "b"]).await;
cx.assert_shared_state(indoc! { "The «ˇquick brown
cx.simulate_shared_keystrokes("v k b").await;
cx.shared_state()
.await
.assert_eq(indoc! { "The «ˇquick brown
fox jumps o»ver
the lazy dog"})
.await;
the lazy dog"});
// works on empty lines
cx.set_shared_state(indoc! {"
@ -633,23 +632,21 @@ mod test {
"})
.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! {"
cx.simulate_shared_keystrokes("v").await;
cx.shared_state().await.assert_eq(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! {"
cx.simulate_shared_keystrokes("v").await;
cx.shared_state().await.assert_eq(indoc! {"
a
ˇ
b
"})
.await;
"});
// works at the end of a document
cx.set_shared_state(indoc! {"
@ -658,13 +655,11 @@ mod test {
ˇ"})
.await;
cx.simulate_shared_keystrokes(["v"]).await;
cx.assert_shared_state(indoc! {"
cx.simulate_shared_keystrokes("v").await;
cx.shared_state().await.assert_eq(indoc! {"
a
b
ˇ"})
.await;
assert_eq!(cx.mode(), cx.neovim_mode().await);
ˇ"});
}
#[gpui::test]
@ -677,16 +672,15 @@ mod test {
the lazy dog"
})
.await;
cx.simulate_shared_keystrokes(["shift-v"]).await;
cx.assert_shared_state(indoc! { "The «qˇ»uick brown
cx.simulate_shared_keystrokes("shift-v").await;
cx.shared_state()
.await
.assert_eq(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;
the lazy dog"});
cx.simulate_shared_keystrokes("x").await;
cx.shared_state().await.assert_eq(indoc! { "fox ˇjumps over
the lazy dog"});
// it should work on empty lines
cx.set_shared_state(indoc! {"
@ -694,17 +688,15 @@ mod test {
ˇ
b"})
.await;
cx.simulate_shared_keystrokes(["shift-v"]).await;
cx.assert_shared_state(indoc! { "
cx.simulate_shared_keystrokes("shift-v").await;
cx.shared_state().await.assert_eq(indoc! {"
a
«
ˇ»b"})
.await;
cx.simulate_shared_keystrokes(["x"]).await;
cx.assert_shared_state(indoc! { "
ˇ»b"});
cx.simulate_shared_keystrokes("x").await;
cx.shared_state().await.assert_eq(indoc! {"
a
ˇb"})
.await;
ˇb"});
// it should work at the end of the document
cx.set_shared_state(indoc! {"
@ -713,54 +705,60 @@ mod test {
ˇ"})
.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! {"
cx.simulate_shared_keystrokes("shift-v").await;
cx.shared_state().await.assert_eq(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! {"
cx.simulate_shared_keystrokes("x").await;
cx.shared_state().await.assert_eq(indoc! {"
a
ˇb"})
.await;
ˇb"});
}
#[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.simulate("v w", "The quick ˇbrown")
.await
.assert_matches();
cx.assert_binding_matches(["v", "w", "x"], "The quick ˇbrown")
.await;
cx.assert_binding_matches(
["v", "w", "j", "x"],
cx.simulate("v w x", "The quick ˇbrown")
.await
.assert_matches();
cx.simulate(
"v w j x",
indoc! {"
The ˇquick brown
fox jumps over
the lazy dog"},
)
.await;
.await
.assert_matches();
// Test pasting code copied on delete
cx.simulate_shared_keystrokes(["j", "p"]).await;
cx.assert_state_matches().await;
cx.simulate_shared_keystrokes("j p").await;
cx.shared_state().await.assert_matches();
let mut cx = cx.binding(["v", "w", "j", "x"]);
cx.assert_all(indoc! {"
cx.simulate_at_each_offset(
"v w j x",
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 ˇlazy dog"},
)
.await
.assert_matches();
cx.simulate_at_each_offset(
"v b k x",
indoc! {"
The ˇquick brown
fox jumps ˇover
the ˇlazy dog"})
.await;
the ˇlazy dog"},
)
.await
.assert_matches();
}
#[gpui::test]
@ -772,34 +770,32 @@ mod test {
fox jumps over
the lazy dog"})
.await;
cx.simulate_shared_keystrokes(["shift-v", "x"]).await;
cx.assert_state_matches().await;
cx.simulate_shared_keystrokes("shift-v x").await;
cx.shared_state().await.assert_matches();
// Test pasting code copied on delete
cx.simulate_shared_keystroke("p").await;
cx.assert_state_matches().await;
cx.simulate_shared_keystrokes("p").await;
cx.shared_state().await.assert_matches();
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;
cx.simulate_shared_keystrokes("shift-v x").await;
cx.shared_state().await.assert_matches();
cx.shared_clipboard().await.assert_eq("the lazy dog\n");
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 quˇick brown
fox jumps over
the lazy dog"})
.await;
cx.simulate_shared_keystrokes("shift-v j x").await;
cx.shared_state().await.assert_matches();
// Test pasting code copied on delete
cx.simulate_shared_keystrokes("p").await;
cx.shared_state().await.assert_matches();
cx.set_shared_state(indoc! {"
The ˇlong line
@ -807,8 +803,8 @@ mod test {
crash
"})
.await;
cx.simulate_shared_keystrokes(["shift-v", "$", "x"]).await;
cx.assert_state_matches().await;
cx.simulate_shared_keystrokes("shift-v $ x").await;
cx.shared_state().await.assert_matches();
}
#[gpui::test]
@ -816,53 +812,48 @@ mod test {
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.simulate_shared_keystrokes("v w y").await;
cx.shared_state().await.assert_eq("The quick ˇbrown");
cx.shared_clipboard().await.assert_eq("brown");
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! {"
cx.simulate_shared_keystrokes("v w j y").await;
cx.shared_state().await.assert_eq(indoc! {"
The ˇquick brown
fox jumps over
the lazy dog"})
.await;
cx.assert_shared_clipboard(indoc! {"
the lazy dog"});
cx.shared_clipboard().await.assert_eq(indoc! {"
quick brown
fox jumps o"})
.await;
fox jumps o"});
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! {"
cx.simulate_shared_keystrokes("v w j y").await;
cx.shared_state().await.assert_eq(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;
the ˇlazy dog"});
cx.shared_clipboard().await.assert_eq("lazy d");
cx.simulate_shared_keystrokes("shift-v y").await;
cx.shared_clipboard().await.assert_eq("the lazy dog\n");
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! {"
cx.simulate_shared_keystrokes("v b k y").await;
cx.shared_state().await.assert_eq(indoc! {"
ˇThe quick brown
fox jumps over
the lazy dog"})
.await;
the lazy dog"});
assert_eq!(
cx.read_from_clipboard()
.map(|item| item.text().clone())
@ -875,15 +866,15 @@ mod test {
fox ˇjumps over
the lazy dog"})
.await;
cx.simulate_shared_keystrokes(["shift-v", "shift-g", "shift-y"])
cx.simulate_shared_keystrokes("shift-v shift-g shift-y")
.await;
cx.assert_shared_state(indoc! {"
cx.shared_state().await.assert_eq(indoc! {"
The quick brown
ˇfox jumps over
the lazy dog"})
.await;
cx.assert_shared_clipboard("fox jumps over\nthe lazy dog\n")
.await;
the lazy dog"});
cx.shared_clipboard()
.await
.assert_eq("fox jumps over\nthe lazy dog\n");
}
#[gpui::test]
@ -896,64 +887,56 @@ mod test {
the lazy dog"
})
.await;
cx.simulate_shared_keystrokes(["ctrl-v"]).await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes("ctrl-v").await;
cx.shared_state().await.assert_eq(indoc! {
"The «qˇ»uick brown
fox jumps over
the lazy dog"
})
.await;
cx.simulate_shared_keystrokes(["2", "down"]).await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes("2 down").await;
cx.shared_state().await.assert_eq(indoc! {
"The «qˇ»uick brown
fox «»umps over
the «»azy dog"
})
.await;
cx.simulate_shared_keystrokes(["e"]).await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes("e").await;
cx.shared_state().await.assert_eq(indoc! {
"The «quicˇ»k brown
fox «jumpˇ»s over
the «lazyˇ» dog"
})
.await;
cx.simulate_shared_keystrokes(["^"]).await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes("^").await;
cx.shared_state().await.assert_eq(indoc! {
"«ˇThe q»uick brown
«ˇfox j»umps over
«ˇthe l»azy dog"
})
.await;
cx.simulate_shared_keystrokes(["$"]).await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes("$").await;
cx.shared_state().await.assert_eq(indoc! {
"The «quick brownˇ»
fox «jumps overˇ»
the «lazy dogˇ»"
})
.await;
cx.simulate_shared_keystrokes(["shift-f", " "]).await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes("shift-f space").await;
cx.shared_state().await.assert_eq(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! {
cx.simulate_shared_keystrokes("v").await;
cx.shared_state().await.assert_eq(indoc! {
"The «quick brown
fox jumps over
the lazy ˇ»dog"
})
.await;
cx.simulate_shared_keystrokes(["ctrl-v"]).await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes("ctrl-v").await;
cx.shared_state().await.assert_eq(indoc! {
"The «quickˇ» brown
fox «jumpsˇ» over
the «lazy ˇ»dog"
})
.await;
});
cx.set_shared_state(indoc! {
"The ˇquick
@ -965,9 +948,8 @@ mod test {
"
})
.await;
cx.simulate_shared_keystrokes(["ctrl-v", "down", "down"])
.await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes("ctrl-v down down").await;
cx.shared_state().await.assert_eq(indoc! {
"The«ˇ q»uick
bro«ˇwn»
foxˇ
@ -975,10 +957,9 @@ mod test {
lazy dog
"
})
.await;
cx.simulate_shared_keystrokes(["down"]).await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes("down").await;
cx.shared_state().await.assert_eq(indoc! {
"The «qˇ»uick
brow«»
fox
@ -986,10 +967,9 @@ mod test {
lazy dog
"
})
.await;
cx.simulate_shared_keystroke("left").await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes("left").await;
cx.shared_state().await.assert_eq(indoc! {
"The«ˇ q»uick
bro«ˇwn»
foxˇ
@ -997,10 +977,9 @@ mod test {
lazy dog
"
})
.await;
cx.simulate_shared_keystrokes(["s", "o", "escape"]).await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes("s o escape").await;
cx.shared_state().await.assert_eq(indoc! {
"Theˇouick
broo
foxo
@ -1008,8 +987,7 @@ mod test {
lazy dog
"
})
.await;
});
// https://github.com/zed-industries/zed/issues/6274
cx.set_shared_state(indoc! {
@ -1020,16 +998,14 @@ mod test {
"
})
.await;
cx.simulate_shared_keystrokes(["l", "ctrl-v", "j", "j"])
.await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes("l ctrl-v j j").await;
cx.shared_state().await.assert_eq(indoc! {
"The «qˇ»uick brown
fox «»umps over
the lazy dog
"
})
.await;
});
}
#[gpui::test]
@ -1043,15 +1019,13 @@ mod test {
"
})
.await;
cx.simulate_shared_keystrokes(["ctrl-v", "right", "down"])
.await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes("ctrl-v right down").await;
cx.shared_state().await.assert_eq(indoc! {
"The «quˇ»ick brown
fox «juˇ»mps over
the lazy dog
"
})
.await;
});
}
#[gpui::test]
@ -1065,24 +1039,21 @@ mod test {
"
})
.await;
cx.simulate_shared_keystrokes(["ctrl-v", "9", "down"]).await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes("ctrl-v 9 down").await;
cx.shared_state().await.assert_eq(indoc! {
"«Tˇ»he quick brown
«»ox jumps over
«»he lazy dog
ˇ"
})
.await;
});
cx.simulate_shared_keystrokes(["shift-i", "k", "escape"])
.await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes("shift-i k escape").await;
cx.shared_state().await.assert_eq(indoc! {
"ˇkThe quick brown
kfox jumps over
kthe lazy dog
k"
})
.await;
});
cx.set_shared_state(indoc! {
"ˇThe quick brown
@ -1091,22 +1062,20 @@ mod test {
"
})
.await;
cx.simulate_shared_keystrokes(["ctrl-v", "9", "down"]).await;
cx.assert_shared_state(indoc! {
cx.simulate_shared_keystrokes("ctrl-v 9 down").await;
cx.shared_state().await.assert_eq(indoc! {
"«Tˇ»he quick brown
«»ox jumps over
«»he lazy dog
ˇ"
})
.await;
cx.simulate_shared_keystrokes(["c", "k", "escape"]).await;
cx.assert_shared_state(indoc! {
});
cx.simulate_shared_keystrokes("c k escape").await;
cx.shared_state().await.assert_eq(indoc! {
"ˇkhe quick brown
kox jumps over
khe lazy dog
k"
})
.await;
});
}
#[gpui::test]
@ -1114,19 +1083,26 @@ mod test {
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;
cx.simulate_shared_keystrokes(["i", "("]).await;
cx.assert_shared_state("hello («in [parens] oˇ»)").await;
cx.simulate_shared_keystrokes("ctrl-v l").await;
cx.simulate_shared_keystrokes("a ]").await;
cx.shared_state()
.await
.assert_eq("hello (in «[parens]ˇ» o)");
cx.simulate_shared_keystrokes("i (").await;
cx.shared_state()
.await
.assert_eq("hello («in [parens] oˇ»)");
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;
cx.simulate_shared_keystrokes("ctrl-v l i w").await;
cx.shared_state()
.await
.assert_eq("hello in a w«ordˇ» again.");
assert_eq!(cx.mode(), Mode::VisualBlock);
cx.simulate_shared_keystrokes(["o", "a", "s"]).await;
cx.assert_shared_state("«ˇhello in a word» again.").await;
cx.simulate_shared_keystrokes("o a s").await;
cx.shared_state()
.await
.assert_eq("«ˇhello in a word» again.");
}
#[gpui::test]
@ -1134,9 +1110,9 @@ mod test {
let mut cx = VimTestContext::new(cx, true).await;
cx.set_state("aˇbc", Mode::Normal);
cx.simulate_keystrokes(["ctrl-v"]);
cx.simulate_keystrokes("ctrl-v");
assert_eq!(cx.mode(), Mode::VisualBlock);
cx.simulate_keystrokes(["cmd-shift-p", "escape"]);
cx.simulate_keystrokes("cmd-shift-p escape");
assert_eq!(cx.mode(), Mode::VisualBlock);
}
@ -1145,32 +1121,28 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.set_shared_state("aaˇ aa aa aa aa").await;
cx.simulate_shared_keystrokes(["/", "a", "a", "enter"])
.await;
cx.assert_shared_state("aa ˇaa aa aa aa").await;
cx.simulate_shared_keystrokes(["g", "n"]).await;
cx.assert_shared_state("aa «aaˇ» aa aa aa").await;
cx.simulate_shared_keystrokes(["g", "n"]).await;
cx.assert_shared_state("aa «aa aaˇ» aa aa").await;
cx.simulate_shared_keystrokes(["escape", "d", "g", "n"])
.await;
cx.assert_shared_state("aa aa ˇ aa aa").await;
cx.simulate_shared_keystrokes("/ a a enter").await;
cx.shared_state().await.assert_eq("aa ˇaa aa aa aa");
cx.simulate_shared_keystrokes("g n").await;
cx.shared_state().await.assert_eq("aa «aaˇ» aa aa aa");
cx.simulate_shared_keystrokes("g n").await;
cx.shared_state().await.assert_eq("aa «aa aaˇ» aa aa");
cx.simulate_shared_keystrokes("escape d g n").await;
cx.shared_state().await.assert_eq("aa aa ˇ aa aa");
cx.set_shared_state("aaˇ aa aa aa aa").await;
cx.simulate_shared_keystrokes(["/", "a", "a", "enter"])
.await;
cx.assert_shared_state("aa ˇaa aa aa aa").await;
cx.simulate_shared_keystrokes(["3", "g", "n"]).await;
cx.assert_shared_state("aa aa aa «aaˇ» aa").await;
cx.simulate_shared_keystrokes("/ a a enter").await;
cx.shared_state().await.assert_eq("aa ˇaa aa aa aa");
cx.simulate_shared_keystrokes("3 g n").await;
cx.shared_state().await.assert_eq("aa aa aa «aaˇ» aa");
cx.set_shared_state("aaˇ aa aa aa aa").await;
cx.simulate_shared_keystrokes(["/", "a", "a", "enter"])
.await;
cx.assert_shared_state("aa ˇaa aa aa aa").await;
cx.simulate_shared_keystrokes(["g", "shift-n"]).await;
cx.assert_shared_state("aa «ˇaa» aa aa aa").await;
cx.simulate_shared_keystrokes(["g", "shift-n"]).await;
cx.assert_shared_state("«ˇaa aa» aa aa aa").await;
cx.simulate_shared_keystrokes("/ a a enter").await;
cx.shared_state().await.assert_eq("aa ˇaa aa aa aa");
cx.simulate_shared_keystrokes("g shift-n").await;
cx.shared_state().await.assert_eq("aa «ˇaa» aa aa aa");
cx.simulate_shared_keystrokes("g shift-n").await;
cx.shared_state().await.assert_eq("«ˇaa aa» aa aa aa");
}
#[gpui::test]
@ -1178,16 +1150,15 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.set_shared_state("aaˇ aa aa aa aa").await;
cx.simulate_shared_keystrokes(["/", "a", "a", "enter"])
.await;
cx.assert_shared_state("aa ˇaa aa aa aa").await;
cx.simulate_shared_keystrokes(["d", "g", "n"]).await;
cx.simulate_shared_keystrokes("/ a a enter").await;
cx.shared_state().await.assert_eq("aa ˇaa aa aa aa");
cx.simulate_shared_keystrokes("d g n").await;
cx.assert_shared_state("aa ˇ aa aa aa").await;
cx.simulate_shared_keystrokes(["."]).await;
cx.assert_shared_state("aa ˇ aa aa").await;
cx.simulate_shared_keystrokes(["."]).await;
cx.assert_shared_state("aa ˇ aa").await;
cx.shared_state().await.assert_eq("aa ˇ aa aa aa");
cx.simulate_shared_keystrokes(".").await;
cx.shared_state().await.assert_eq("aa ˇ aa aa");
cx.simulate_shared_keystrokes(".").await;
cx.shared_state().await.assert_eq("aa ˇ aa");
}
#[gpui::test]
@ -1195,14 +1166,12 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.set_shared_state("aaˇ aa aa aa aa").await;
cx.simulate_shared_keystrokes(["/", "a", "a", "enter"])
.await;
cx.assert_shared_state("aa ˇaa aa aa aa").await;
cx.simulate_shared_keystrokes(["c", "g", "n", "x", "escape"])
.await;
cx.assert_shared_state("aa ˇx aa aa aa").await;
cx.simulate_shared_keystrokes(["."]).await;
cx.assert_shared_state("aa x ˇx aa aa").await;
cx.simulate_shared_keystrokes("/ a a enter").await;
cx.shared_state().await.assert_eq("aa ˇaa aa aa aa");
cx.simulate_shared_keystrokes("c g n x escape").await;
cx.shared_state().await.assert_eq("aa ˇx aa aa aa");
cx.simulate_shared_keystrokes(".").await;
cx.shared_state().await.assert_eq("aa x ˇx aa aa");
}
#[gpui::test]
@ -1210,23 +1179,19 @@ mod test {
let mut cx = NeovimBackedTestContext::new(cx).await;
cx.set_shared_state("aaˇ aa aa aa aa").await;
cx.simulate_shared_keystrokes(["/", "b", "b", "enter"])
.await;
cx.assert_shared_state("aaˇ aa aa aa aa").await;
cx.simulate_shared_keystrokes(["c", "g", "n", "x", "escape"])
.await;
cx.assert_shared_state("aaˇaa aa aa aa").await;
cx.simulate_shared_keystrokes(["."]).await;
cx.assert_shared_state("aaˇa aa aa aa").await;
cx.simulate_shared_keystrokes("/ b b enter").await;
cx.shared_state().await.assert_eq("aaˇ aa aa aa aa");
cx.simulate_shared_keystrokes("c g n x escape").await;
cx.shared_state().await.assert_eq("aaˇaa aa aa aa");
cx.simulate_shared_keystrokes(".").await;
cx.shared_state().await.assert_eq("aaˇa aa aa aa");
cx.set_shared_state("aaˇ bb aa aa aa").await;
cx.simulate_shared_keystrokes(["/", "b", "b", "enter"])
.await;
cx.assert_shared_state("aa ˇbb aa aa aa").await;
cx.simulate_shared_keystrokes(["c", "g", "n", "x", "escape"])
.await;
cx.assert_shared_state("aa ˇx aa aa aa").await;
cx.simulate_shared_keystrokes(["."]).await;
cx.assert_shared_state("aa ˇx aa aa aa").await;
cx.simulate_shared_keystrokes("/ b b enter").await;
cx.shared_state().await.assert_eq("aa ˇbb aa aa aa");
cx.simulate_shared_keystrokes("c g n x escape").await;
cx.shared_state().await.assert_eq("aa ˇx aa aa aa");
cx.simulate_shared_keystrokes(".").await;
cx.shared_state().await.assert_eq("aa ˇx aa aa aa");
}
}

View File

@ -9,7 +9,7 @@
{"Key":"g"}
{"Key":"h"}
{"Key":"t"}
{"Key":" "}
{"Key":"space"}
{"Key":"t"}
{"Key":"h"}
{"Key":"i"}

View File

@ -6,7 +6,7 @@
{"Key":"c"}
{"Key":"c"}
{"Get":{"state":"ˇ\nbrown fox\njumps over\nthe lazy","mode":"Insert"}}
{"Put":{"state":"The quick\n broˇwn fox\njumˇps over\nthe lazy"}}
{"Put":{"state":"The quick\n broˇwn fox\njumps over\nthe lazy"}}
{"Key":"c"}
{"Key":"c"}
{"Get":{"state":"The quick\n ˇ\nˇ\nthe lazy","mode":"Insert"}}
{"Get":{"state":"The quick\n ˇ\njumps over\nthe lazy","mode":"Insert"}}

View File

@ -1,3 +1,11 @@
{"Put":{"state":"Teˇst Test\n"}}
{"Key":"d"}
{"Key":"e"}
{"Get":{"state":"Teˇ Test\n","mode":"Normal"}}
{"Put":{"state":"Tˇest test\n"}}
{"Key":"d"}
{"Key":"e"}
{"Get":{"state":"Tˇ test\n","mode":"Normal"}}
{"Put":{"state":"Test teˇst\ntest"}}
{"Key":"d"}
{"Key":"e"}
@ -8,5 +16,5 @@
{"Get":{"state":"Test teˇs","mode":"Normal"}}
{"Put":{"state":"Test teˇst-test test"}}
{"Key":"d"}
{"Key":"shift-e"}
{"Get":{"state":"Test teˇ test","mode":"Normal"}}
{"Key":"e"}
{"Get":{"state":"Test teˇ-test test","mode":"Normal"}}

View File

@ -17,6 +17,7 @@
{"Key":"down"}
{"Key":"y"}
{"Key":"y"}
{"Get":{"state":"fn boop() {\nˇ barp()\n bazp()\n}\n","mode":"Normal"}}
{"ReadRegister":{"name":"\"","value":" barp()\n bazp()\n"}}
{"Key":"z"}
{"Key":"o"}

View File

@ -1,10 +1,10 @@
{"Key":"i"}
{"Get":{"state":"ˇ","mode":"Insert"}}
{"Key":"shift-T"}
{"Key":"shift-t"}
{"Key":"e"}
{"Key":"s"}
{"Key":"t"}
{"Key":" "}
{"Key":"space"}
{"Key":"t"}
{"Key":"e"}
{"Key":"s"}

View File

@ -2,6 +2,7 @@
{"Key":"v"}
{"Key":"w"}
{"Key":"y"}
{"Get":{"state":"The quick brown\nfox ˇjumps over\nthe lazy dog","mode":"Normal"}}
{"ReadRegister":{"name":"\"","value":"jumps o"}}
{"Put":{"state":"The quick brown\nfox jumps oveˇr\nthe lazy dog"}}
{"Key":"p"}
@ -12,6 +13,7 @@
{"Put":{"state":"The quick brown\nfox juˇmps over\nthe lazy dog"}}
{"Key":"d"}
{"Key":"d"}
{"Get":{"state":"The quick brown\nthe laˇzy dog","mode":"Normal"}}
{"ReadRegister":{"name":"\"","value":"fox jumps over\n"}}
{"Get":{"state":"The quick brown\nthe laˇzy dog","mode":"Normal"}}
{"Key":"p"}
@ -23,6 +25,7 @@
{"Key":"v"}
{"Key":"j"}
{"Key":"y"}
{"Get":{"state":"The quick brown\nfox jumps ˇover\nthe lazy dog","mode":"Normal"}}
{"ReadRegister":{"name":"\"","value":"over\nthe lazy do"}}
{"Key":"p"}
{"Get":{"state":"The quick brown\nfox jumps oˇover\nthe lazy dover\nthe lazy dog","mode":"Normal"}}

View File

@ -3,6 +3,7 @@
{"Key":"2"}
{"Key":"j"}
{"Key":"y"}
{"Get":{"state":"The ˇquick brown\nfox jumps over\nthe lazy dog","mode":"Normal"}}
{"ReadRegister":{"name":"\"","value":"q\nj\nl"}}
{"Key":"p"}
{"Get":{"state":"The qˇquick brown\nfox jjumps over\nthe llazy dog","mode":"Normal"}}
@ -19,6 +20,7 @@
{"Key":"ctrl-v"}
{"Key":"j"}
{"Key":"y"}
{"Get":{"state":"The ˇquick brown\nfox jumps over\nthe lazy dog","mode":"Normal"}}
{"ReadRegister":{"name":"\"","value":"q\nj"}}
{"Key":"l"}
{"Key":"ctrl-v"}

View File

@ -16,12 +16,6 @@
{"Key":"n"}
{"Key":"e"}
{"Get":{"state":"The quick brown\nOneˇ\nfox jumps over\nthe lazy dog.","mode":"Replace"}}
{"Put":{"state":"ˇThe quick brown\nfox jumps over\nthe lazy ˇdog."}}
{"Key":"shift-r"}
{"Key":"O"}
{"Key":"n"}
{"Key":"e"}
{"Get":{"state":"Oneˇ quick brown\nfox jumps over\nthe lazy Oneˇ.","mode":"Replace"}}
{"Put":{"state":"The quˇick brown\nfox jumps over\nthe lazy dog."}}
{"Key":"shift-r"}
{"Key":"enter"}
@ -29,20 +23,3 @@
{"Key":"n"}
{"Key":"e"}
{"Get":{"state":"The qu\nOneˇ brown\nfox jumps over\nthe lazy dog.","mode":"Replace"}}
{"Put":{"state":"ˇThe quick brown\nfox jumps over\nthe lazy ˇdog."}}
{"Key":"shift-r"}
{"Key":"O"}
{"Key":"n"}
{"Key":"e"}
{"Get":{"state":"Oneˇ quick brown\nfox jumps over\nthe lazy Oneˇ.","mode":"Replace"}}
{"Key":"enter"}
{"Key":"T"}
{"Key":"w"}
{"Key":"o"}
{"Get":{"state":"One\nTwoˇck brown\nfox jumps over\nthe lazy One\nTwoˇ","mode":"Replace"}}
{"Put":{"state":"ˇThe quick brown\nfox jumps over\nthe lazy ˇdog."}}
{"Key":"shift-r"}
{"Key":"O"}
{"Key":"n"}
{"Key":"e"}
{"Get":{"state":"Oneˇ quick brown\nfox jumps over\nthe lazy Oneˇ.","mode":"Replace"}}

View File

@ -91,34 +91,3 @@
{"Key":"backspace"}
{"Key":"backspace"}
{"Get":{"state":"The quick brown\nˇ\nfox jumps over\nthe lazy dog.","mode":"Replace"}}
{"Put":{"state":"The quick browˇn\nfox jumps over\nthe lazy ˇdog."}}
{"Key":"shift-r"}
{"Key":"O"}
{"Key":"n"}
{"Key":"e"}
{"Key":"backspace"}
{"Key":"backspace"}
{"Key":"backspace"}
{"Get":{"state":"The quick browˇn\nfox jumps over\nthe lazy ˇdog.","mode":"Replace"}}
{"Put":{"state":"The quick browˇn\nfox jumps over\nthe lazy ˇdog."}}
{"Key":"shift-r"}
{"Key":"O"}
{"Key":"enter"}
{"Key":"e"}
{"Key":"backspace"}
{"Key":"backspace"}
{"Key":"backspace"}
{"Get":{"state":"The quick browˇn\nfox jumps over\nthe lazy ˇdog.","mode":"Replace"}}
{"Put":{"state":"The quick browˇn\nfox jumps over\nthe lazy ˇdog."}}
{"Key":"shift-r"}
{"Key":"O"}
{"Key":"enter"}
{"Key":"n"}
{"Key":"enter"}
{"Key":"e"}
{"Key":"backspace"}
{"Key":"backspace"}
{"Key":"backspace"}
{"Key":"backspace"}
{"Key":"backspace"}
{"Get":{"state":"The quick browˇn\nfox jumps over\nthe lazy ˇdog.","mode":"Replace"}}

View File

@ -11,7 +11,7 @@
{"Key":"$"}
{"Get":{"state":"The «quick brownˇ»\nfox «jumps overˇ»\nthe «lazy dogˇ»","mode":"VisualBlock"}}
{"Key":"shift-f"}
{"Key":" "}
{"Key":"space"}
{"Get":{"state":"The «quickˇ» brown\nfox «jumpsˇ» over\nthe «lazy ˇ»dog","mode":"VisualBlock"}}
{"Key":"v"}
{"Get":{"state":"The «quick brown\nfox jumps over\nthe lazy ˇ»dog","mode":"Visual"}}

View File

@ -15,6 +15,18 @@
{"Key":"j"}
{"Key":"c"}
{"Get":{"state":"The ˇver\nthe lazy dog","mode":"Insert"}}
{"Put":{"state":"The quick brown\nfox jumps ˇover\nthe lazy dog"}}
{"Key":"v"}
{"Key":"w"}
{"Key":"j"}
{"Key":"c"}
{"Get":{"state":"The quick brown\nfox jumps ˇhe lazy dog","mode":"Insert"}}
{"Put":{"state":"The quick brown\nfox jumps over\nthe ˇlazy dog"}}
{"Key":"v"}
{"Key":"w"}
{"Key":"j"}
{"Key":"c"}
{"Get":{"state":"The quick brown\nfox jumps over\nthe ˇog","mode":"Insert"}}
{"Put":{"state":"The ˇquick brown\nfox jumps over\nthe lazy dog"}}
{"Key":"v"}
{"Key":"w"}
@ -24,24 +36,12 @@
{"Put":{"state":"The quick brown\nfox jumps ˇover\nthe lazy dog"}}
{"Key":"v"}
{"Key":"w"}
{"Key":"j"}
{"Key":"c"}
{"Get":{"state":"The quick brown\nfox jumps ˇhe lazy dog","mode":"Insert"}}
{"Put":{"state":"The quick brown\nfox jumps ˇover\nthe lazy dog"}}
{"Key":"v"}
{"Key":"w"}
{"Key":"k"}
{"Key":"c"}
{"Get":{"state":"The quick brown\nˇver\nthe lazy dog","mode":"Insert"}}
{"Put":{"state":"The quick brown\nfox jumps over\nthe ˇlazy dog"}}
{"Key":"v"}
{"Key":"w"}
{"Key":"j"}
{"Key":"c"}
{"Get":{"state":"The quick brown\nfox jumps over\nthe ˇog","mode":"Insert"}}
{"Put":{"state":"The quick brown\nfox jumps over\nthe ˇlazy dog"}}
{"Key":"v"}
{"Key":"w"}
{"Key":"k"}
{"Key":"c"}
{"Get":{"state":"The quick brown\nfox jumpsˇazy dog","mode":"Insert"}}

View File

@ -20,6 +20,7 @@
{"ReadRegister":{"name":"\"","value":"lazy d"}}
{"Key":"shift-v"}
{"Key":"y"}
{"Get":{"state":"The quick brown\nfox jumps over\nˇthe lazy dog","mode":"Normal"}}
{"ReadRegister":{"name":"\"","value":"the lazy dog\n"}}
{"Put":{"state":"The ˇquick brown\nfox jumps over\nthe lazy dog"}}
{"Key":"v"}