Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'helix-term/tests/test/commands/movement.rs')
| -rw-r--r-- | helix-term/tests/test/commands/movement.rs | 650 |
1 files changed, 76 insertions, 574 deletions
diff --git a/helix-term/tests/test/commands/movement.rs b/helix-term/tests/test/commands/movement.rs index 5868fa49..5be68837 100644 --- a/helix-term/tests/test/commands/movement.rs +++ b/helix-term/tests/test/commands/movement.rs @@ -6,7 +6,7 @@ async fn test_move_parent_node_end() -> anyhow::Result<()> { // single cursor stays single cursor, first goes to end of current // node, then parent ( - indoc! {r##" + helpers::platform_line(indoc! {r##" fn foo() { let result = if true { "yes" @@ -14,9 +14,9 @@ async fn test_move_parent_node_end() -> anyhow::Result<()> { "no#["|]# } } - "##}, + "##}), "<A-e>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -24,10 +24,10 @@ async fn test_move_parent_node_end() -> anyhow::Result<()> { \"no\"#[\n|]# } } - "}, + "}), ), ( - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -35,9 +35,9 @@ async fn test_move_parent_node_end() -> anyhow::Result<()> { \"no\"#[\n|]# } } - "}, + "}), "<A-e>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -45,11 +45,11 @@ async fn test_move_parent_node_end() -> anyhow::Result<()> { \"no\" }#[\n|]# } - "}, + "}), ), // select mode extends ( - indoc! {r##" + helpers::platform_line(indoc! {r##" fn foo() { let result = if true { "yes" @@ -57,9 +57,9 @@ async fn test_move_parent_node_end() -> anyhow::Result<()> { #["no"|]# } } - "##}, + "##}), "v<A-e><A-e>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -67,7 +67,7 @@ async fn test_move_parent_node_end() -> anyhow::Result<()> { #[\"no\" }\n|]# } - "}, + "}), ), ]; @@ -84,7 +84,7 @@ async fn test_move_parent_node_start() -> anyhow::Result<()> { // single cursor stays single cursor, first goes to end of current // node, then parent ( - indoc! {r##" + helpers::platform_line(indoc! {r##" fn foo() { let result = if true { "yes" @@ -92,9 +92,9 @@ async fn test_move_parent_node_start() -> anyhow::Result<()> { "no#["|]# } } - "##}, + "##}), "<A-b>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -102,10 +102,10 @@ async fn test_move_parent_node_start() -> anyhow::Result<()> { #[\"|]#no\" } } - "}, + "}), ), ( - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -113,9 +113,9 @@ async fn test_move_parent_node_start() -> anyhow::Result<()> { \"no\"#[\n|]# } } - "}, + "}), "<A-b>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -123,10 +123,10 @@ async fn test_move_parent_node_start() -> anyhow::Result<()> { \"no\" } } - "}, + "}), ), ( - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -134,9 +134,9 @@ async fn test_move_parent_node_start() -> anyhow::Result<()> { \"no\" } } - "}, + "}), "<A-b>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -144,11 +144,11 @@ async fn test_move_parent_node_start() -> anyhow::Result<()> { \"no\" } } - "}, + "}), ), // select mode extends ( - indoc! {r##" + helpers::platform_line(indoc! {r##" fn foo() { let result = if true { "yes" @@ -156,9 +156,9 @@ async fn test_move_parent_node_start() -> anyhow::Result<()> { #["no"|]# } } - "##}, + "##}), "v<A-b><A-b>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -166,10 +166,10 @@ async fn test_move_parent_node_start() -> anyhow::Result<()> { ]#\"no\" } } - "}, + "}), ), ( - indoc! {r##" + helpers::platform_line(indoc! {r##" fn foo() { let result = if true { "yes" @@ -177,9 +177,9 @@ async fn test_move_parent_node_start() -> anyhow::Result<()> { #["no"|]# } } - "##}, + "##}), "v<A-b><A-b><A-b>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -187,7 +187,7 @@ async fn test_move_parent_node_start() -> anyhow::Result<()> { ]#\"no\" } } - "}, + "}), ), ]; @@ -204,7 +204,7 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { // single cursor stays single cursor, first goes to end of current // node, then parent ( - indoc! {r##" + helpers::platform_line(indoc! {r##" fn foo() { let result = if true { "yes" @@ -212,9 +212,9 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { "no#["|]# } } - "##}, + "##}), "i<tab>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -222,10 +222,10 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { \"no\"#[|\n]# } } - "}, + "}), ), ( - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -233,9 +233,9 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { \"no\"#[\n|]# } } - "}, + "}), "i<tab>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -243,12 +243,12 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { \"no\" }#[|\n]# } - "}, + "}), ), // appending to the end of a line should still look at the current // line, not the next one ( - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -256,9 +256,9 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { \"no#[\"|]# } } - "}, + "}), "a<tab>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -266,11 +266,11 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { \"no\" }#[\n|]# } - "}, + "}), ), // before cursor is all whitespace, so insert tab ( - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -278,9 +278,9 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { #[\"no\"|]# } } - "}, + "}), "i<tab>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -288,12 +288,12 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { #[|\"no\"]# } } - "}, + "}), ), // if selection spans multiple lines, it should still only look at the // line on which the head is ( - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { #[\"yes\" @@ -301,9 +301,9 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { \"no\"|]# } } - "}, + "}), "a<tab>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -311,10 +311,10 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { \"no\" }#[\n|]# } - "}, + "}), ), ( - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { #[\"yes\" @@ -322,9 +322,9 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { \"no\"|]# } } - "}, + "}), "i<tab>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { #[|\"yes\" @@ -332,10 +332,10 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { \"no\"]# } } - "}, + "}), ), ( - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { #[l|]#et result = if true { #(\"yes\" @@ -343,9 +343,9 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { \"no\"|)# } } - "}, + "}), "i<tab>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { #[|l]#et result = if true { #(|\"yes\" @@ -353,10 +353,10 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { \"no\")# } } - "}, + "}), ), ( - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\"#[\n|]# @@ -364,9 +364,9 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { \"no\"#(\n|)# } } - "}, + "}), "i<tab>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -374,10 +374,10 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { \"no\" }#(|\n)# } - "}, + "}), ), ( - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { #[\"yes\"|]# @@ -385,9 +385,9 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { #(\"no\"|)# } } - "}, + "}), "i<tab>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { #[|\"yes\"]# @@ -395,12 +395,12 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { #(|\"no\")# } } - "}, + "}), ), // if any cursors are not preceded by all whitespace, then do the // smart_tab action ( - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { #[\"yes\"\n|]# @@ -408,9 +408,9 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { \"no#(\"\n|)# } } - "}, + "}), "i<tab>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { \"yes\" @@ -418,11 +418,11 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { \"no\" }#(|\n)# } - "}, + "}), ), // Ctrl-tab always inserts a tab ( - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { #[\"yes\"\n|]# @@ -430,9 +430,9 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { \"no#(\"\n|)# } } - "}, + "}), "i<S-tab>", - indoc! {"\ + helpers::platform_line(indoc! {"\ fn foo() { let result = if true { #[|\"yes\"\n]# @@ -440,7 +440,7 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { \"no #(|\"\n)# } } - "}, + "}), ), ]; @@ -450,501 +450,3 @@ async fn test_smart_tab_move_parent_node_end() -> anyhow::Result<()> { Ok(()) } - -#[tokio::test(flavor = "multi_thread")] -async fn select_all_siblings() -> anyhow::Result<()> { - let tests = vec![ - // basic tests - ( - indoc! {r##" - let foo = bar(#[a|]#, b, c); - "##}, - "<A-a>", - indoc! {r##" - let foo = bar(#[a|]#, #(b|)#, #(c|)#); - "##}, - ), - ( - indoc! {r##" - let a = [ - #[1|]#, - 2, - 3, - 4, - 5, - ]; - "##}, - "<A-a>", - indoc! {r##" - let a = [ - #[1|]#, - #(2|)#, - #(3|)#, - #(4|)#, - #(5|)#, - ]; - "##}, - ), - // direction is preserved - ( - indoc! {r##" - let a = [ - #[|1]#, - 2, - 3, - 4, - 5, - ]; - "##}, - "<A-a>", - indoc! {r##" - let a = [ - #[|1]#, - #(|2)#, - #(|3)#, - #(|4)#, - #(|5)#, - ]; - "##}, - ), - // can't pick any more siblings - selection stays the same - ( - indoc! {r##" - let a = [ - #[1|]#, - #(2|)#, - #(3|)#, - #(4|)#, - #(5|)#, - ]; - "##}, - "<A-a>", - indoc! {r##" - let a = [ - #[1|]#, - #(2|)#, - #(3|)#, - #(4|)#, - #(5|)#, - ]; - "##}, - ), - // each cursor does the sibling select independently - ( - indoc! {r##" - let a = [ - #[1|]#, - 2, - 3, - 4, - 5, - ]; - - let b = [ - #("one"|)#, - "two", - "three", - "four", - "five", - ]; - "##}, - "<A-a>", - indoc! {r##" - let a = [ - #[1|]#, - #(2|)#, - #(3|)#, - #(4|)#, - #(5|)#, - ]; - - let b = [ - #("one"|)#, - #("two"|)#, - #("three"|)#, - #("four"|)#, - #("five"|)#, - ]; - "##}, - ), - // conflicting sibling selections get normalized. Here, the primary - // selection would choose every list item, but because the secondary - // range covers more than one item, the descendent is the entire list, - // which means the sibling is the assignment. The list item ranges just - // get normalized out since the list itself becomes selected. - ( - indoc! {r##" - let a = [ - #[1|]#, - 2, - #(3, - 4|)#, - 5, - ]; - "##}, - "<A-a>", - indoc! {r##" - let #(a|)# = #[[ - 1, - 2, - 3, - 4, - 5, - ]|]#; - "##}, - ), - ]; - - for test in tests { - test_with_config(AppBuilder::new().with_file("foo.rs", None), test).await?; - } - - Ok(()) -} - -#[tokio::test(flavor = "multi_thread")] -async fn select_all_children() -> anyhow::Result<()> { - let tests = vec![ - // basic tests - ( - indoc! {r##" - let foo = bar#[(a, b, c)|]#; - "##}, - "<A-I>", - indoc! {r##" - let foo = bar(#[a|]#, #(b|)#, #(c|)#); - "##}, - ), - ( - indoc! {r##" - let a = #[[ - 1, - 2, - 3, - 4, - 5, - ]|]#; - "##}, - "<A-I>", - indoc! {r##" - let a = [ - #[1|]#, - #(2|)#, - #(3|)#, - #(4|)#, - #(5|)#, - ]; - "##}, - ), - // direction is preserved - ( - indoc! {r##" - let a = #[|[ - 1, - 2, - 3, - 4, - 5, - ]]#; - "##}, - "<A-I>", - indoc! {r##" - let a = [ - #[|1]#, - #(|2)#, - #(|3)#, - #(|4)#, - #(|5)#, - ]; - "##}, - ), - // can't pick any more children - selection stays the same - ( - indoc! {r##" - let a = [ - #[1|]#, - #(2|)#, - #(3|)#, - #(4|)#, - #(5|)#, - ]; - "##}, - "<A-I>", - indoc! {r##" - let a = [ - #[1|]#, - #(2|)#, - #(3|)#, - #(4|)#, - #(5|)#, - ]; - "##}, - ), - // each cursor does the sibling select independently - ( - indoc! {r##" - let a = #[|[ - 1, - 2, - 3, - 4, - 5, - ]]#; - - let b = #([ - "one", - "two", - "three", - "four", - "five", - ]|)#; - "##}, - "<A-I>", - indoc! {r##" - let a = [ - #[|1]#, - #(|2)#, - #(|3)#, - #(|4)#, - #(|5)#, - ]; - - let b = [ - #("one"|)#, - #("two"|)#, - #("three"|)#, - #("four"|)#, - #("five"|)#, - ]; - "##}, - ), - ]; - - for test in tests { - test_with_config(AppBuilder::new().with_file("foo.rs", None), test).await?; - } - - Ok(()) -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_select_next_sibling() -> anyhow::Result<()> { - let tests = vec![ - // basic test - ( - indoc! {r##" - fn inc(x: usize) -> usize { x + 1 #[}|]# - fn dec(x: usize) -> usize { x - 1 } - fn ident(x: usize) -> usize { x } - "##}, - "<A-n>", - indoc! {r##" - fn inc(x: usize) -> usize { x + 1 } - #[fn dec(x: usize) -> usize { x - 1 }|]# - fn ident(x: usize) -> usize { x } - "##}, - ), - // direction is not preserved and is always forward. - ( - indoc! {r##" - fn inc(x: usize) -> usize { x + 1 #[}|]# - fn dec(x: usize) -> usize { x - 1 } - fn ident(x: usize) -> usize { x } - "##}, - "<A-n><A-;><A-n>", - indoc! {r##" - fn inc(x: usize) -> usize { x + 1 } - fn dec(x: usize) -> usize { x - 1 } - #[fn ident(x: usize) -> usize { x }|]# - "##}, - ), - ]; - - for test in tests { - test_with_config(AppBuilder::new().with_file("foo.rs", None), test).await?; - } - - Ok(()) -} - -#[tokio::test(flavor = "multi_thread")] -async fn test_select_prev_sibling() -> anyhow::Result<()> { - let tests = vec![ - // basic test - ( - indoc! {r##" - fn inc(x: usize) -> usize { x + 1 } - fn dec(x: usize) -> usize { x - 1 } - #[|f]#n ident(x: usize) -> usize { x } - "##}, - "<A-p>", - indoc! {r##" - fn inc(x: usize) -> usize { x + 1 } - #[|fn dec(x: usize) -> usize { x - 1 }]# - fn ident(x: usize) -> usize { x } - "##}, - ), - // direction is not preserved and is always backward. - ( - indoc! {r##" - fn inc(x: usize) -> usize { x + 1 } - fn dec(x: usize) -> usize { x - 1 } - #[|f]#n ident(x: usize) -> usize { x } - "##}, - "<A-p><A-;><A-p>", - indoc! {r##" - #[|fn inc(x: usize) -> usize { x + 1 }]# - fn dec(x: usize) -> usize { x - 1 } - fn ident(x: usize) -> usize { x } - "##}, - ), - ]; - - for test in tests { - test_with_config(AppBuilder::new().with_file("foo.rs", None), test).await?; - } - - Ok(()) -} - -#[tokio::test(flavor = "multi_thread")] -async fn match_bracket() -> anyhow::Result<()> { - let rust_tests = vec![ - // fwd - ( - indoc! {r##" - fn foo(x: usize) -> usize { #[x|]# + 1 } - "##}, - "mm", - indoc! {r##" - fn foo(x: usize) -> usize { x + 1 #[}|]# - "##}, - ), - // backward - ( - indoc! {r##" - fn foo(x: usize) -> usize { #[x|]# + 1 } - "##}, - "mmmm", - indoc! {r##" - fn foo(x: usize) -> usize #[{|]# x + 1 } - "##}, - ), - // avoid false positive inside string literal - ( - indoc! {r##" - fn foo() -> &'static str { "(hello#[ |]#world)" } - "##}, - "mm", - indoc! {r##" - fn foo() -> &'static str { "(hello world)#["|]# } - "##}, - ), - // make sure matching on quotes works - ( - indoc! {r##" - fn foo() -> &'static str { "(hello#[ |]#world)" } - "##}, - "mm", - indoc! {r##" - fn foo() -> &'static str { "(hello world)#["|]# } - "##}, - ), - // .. on both ends - ( - indoc! {r##" - fn foo() -> &'static str { "(hello#[ |]#world)" } - "##}, - "mmmm", - indoc! {r##" - fn foo() -> &'static str { #["|]#(hello world)" } - "##}, - ), - // match on siblings nodes - ( - indoc! {r##" - fn foo(bar: Option<usize>) -> usize { - match bar { - Some(b#[a|]#r) => bar, - None => 42, - } - } - "##}, - "mmmm", - indoc! {r##" - fn foo(bar: Option<usize>) -> usize { - match bar { - Some#[(|]#bar) => bar, - None => 42, - } - } - "##}, - ), - // gracefully handle multiple sibling brackets (usally for errors/incomplete syntax trees) - // in the past we selected the first > instead of the second > here - ( - indoc! {r##" - fn foo() { - foo::<b#[a|]#r<>> - } - "##}, - "mm", - indoc! {r##" - fn foo() { - foo::<bar<>#[>|]# - } - "##}, - ), - // named node with 2 or more children - ( - indoc! {r##" - use a::#[{|]# - b::{c, d, e, f, g}, - h, i, j, k, l, m, n, - }; - "##}, - "mm", - indoc! {r##" - use a::{ - b::{c, d, e, f, g}, - h, i, j, k, l, m, n, - #[}|]#; - "##}, - ), - ]; - - let python_tests = vec![ - // python quotes have a slightly more complex syntax tree - // that triggerd a bug in an old implementation so we test - // them here - ( - indoc! {r##" - foo_python = "mm does not#[ |]#work on this string" - "##}, - "mm", - indoc! {r##" - foo_python = "mm does not work on this string#["|]# - "##}, - ), - ( - indoc! {r##" - foo_python = "mm does not#[ |]#work on this string" - "##}, - "mmmm", - indoc! {r##" - foo_python = #["|]#mm does not work on this string" - "##}, - ), - ]; - - for test in rust_tests { - println!("{test:?}"); - test_with_config(AppBuilder::new().with_file("foo.rs", None), test).await?; - } - for test in python_tests { - println!("{test:?}"); - test_with_config(AppBuilder::new().with_file("foo.py", None), test).await?; - } - - Ok(()) -} |