aboutsummaryrefslogtreecommitdiff
path: root/helix-term/tests
diff options
context:
space:
mode:
authorDaniel S Poulin2023-02-10 19:52:57 +0000
committerGitHub2023-02-10 19:52:57 +0000
commit6929a12f291fa5dee50cde9c89845b206b7333fd (patch)
tree2dae3acd1ff9064db957f504da52afb41564a613 /helix-term/tests
parentaf1157f37c04e158b96f3e2da7c641356b2219dc (diff)
Make `m` textobject look for pairs enclosing selections (#3344)
* Make `m` textobject look for pairs enclosing selections Right now, this textobject only looks for pairs that surround the cursor. This ensures that the pair found encloses each selection, which is likely to be intuitively what is expected of this textobject. * Simplification of match code Co-authored-by: Michael Davis <mcarsondavis@gmail.com> * Adjust logic for ensuring surround range encloses selection Prior, it was missing the case where the start of the selection came before the opening brace. We also had an off-by-one error where if the end of the selection was on the closing brace it would not work. * Refactor to search for the open pair specifically to avoid edge cases * Adjust wording of autoinfo to reflect new functionality * Implement tests for surround functionality in new integration style * Fix handling of skip values * Fix out of bounds error * Add `ma` version of tests * Fix formatting of tests * Reduce indentation levels for readability, and update comments * Preserve each selection's direction with enclosing pair surround * Add test case for multiple cursors resulting in overlap * Mark known failures as TODO * Make tests multi-threaded or they fail * Cargo fmt * Fix typos in integration test comments --------- Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
Diffstat (limited to 'helix-term/tests')
-rw-r--r--helix-term/tests/test/movement.rs301
1 files changed, 301 insertions, 0 deletions
diff --git a/helix-term/tests/test/movement.rs b/helix-term/tests/test/movement.rs
index fedf4b0e..e6ea3f95 100644
--- a/helix-term/tests/test/movement.rs
+++ b/helix-term/tests/test/movement.rs
@@ -64,6 +64,307 @@ async fn insert_to_normal_mode_cursor_position() -> anyhow::Result<()> {
Ok(())
}
+#[tokio::test(flavor = "multi_thread")]
+async fn surround_by_character() -> anyhow::Result<()> {
+ // Only pairs matching the passed character count
+ test((
+ "(so [many {go#[o|]#d} text] here)",
+ "mi{",
+ "(so [many {#[good|]#} text] here)",
+ ))
+ .await?;
+ test((
+ "(so [many {go#[o|]#d} text] here)",
+ "mi[",
+ "(so [#[many {good} text|]#] here)",
+ ))
+ .await?;
+ test((
+ "(so [many {go#[o|]#d} text] here)",
+ "mi(",
+ "(#[so [many {good} text] here|]#)",
+ ))
+ .await?;
+
+ // Works with characters that aren't pairs too
+ test((
+ "'so 'many 'go#[o|]#d' text' here'",
+ "mi'",
+ "'so 'many '#[good|]#' text' here'",
+ ))
+ .await?;
+ test((
+ "'so 'many 'go#[o|]#d' text' here'",
+ "2mi'",
+ "'so '#[many 'good' text|]#' here'",
+ ))
+ .await?;
+ test((
+ "'so \"many 'go#[o|]#d' text\" here'",
+ "mi\"",
+ "'so \"#[many 'good' text|]#\" here'",
+ ))
+ .await?;
+
+ Ok(())
+}
+
+#[tokio::test(flavor = "multi_thread")]
+async fn surround_inside_pair() -> anyhow::Result<()> {
+ // Works at first character of buffer
+ // TODO: Adjust test when opening pair failure is fixed
+ test(("#[(|]#something)", "mim", "#[(|]#something)")).await?;
+
+ // Inside a valid pair selects pair
+ test(("some (#[t|]#ext) here", "mim", "some (#[text|]#) here")).await?;
+
+ // On pair character selects pair
+ // TODO: Opening pair character is a known failure case that needs addressing
+ // test(("some #[(|]#text) here", "mim", "some (#[text|]#) here")).await?;
+ test(("some (text#[)|]# here", "mim", "some (#[text|]#) here")).await?;
+
+ // No valid pair does nothing
+ test(("so#[m|]#e (text) here", "mim", "so#[m|]#e (text) here")).await?;
+
+ // Count skips to outer pairs
+ test((
+ "(so (many (go#[o|]#d) text) here)",
+ "1mim",
+ "(so (many (#[good|]#) text) here)",
+ ))
+ .await?;
+ test((
+ "(so (many (go#[o|]#d) text) here)",
+ "2mim",
+ "(so (#[many (good) text|]#) here)",
+ ))
+ .await?;
+ test((
+ "(so (many (go#[o|]#d) text) here)",
+ "3mim",
+ "(#[so (many (good) text) here|]#)",
+ ))
+ .await?;
+
+ // Matching pairs outside selection don't match
+ test((
+ "((so)((many) go#[o|]#d (text))(here))",
+ "mim",
+ "((so)(#[(many) good (text)|]#)(here))",
+ ))
+ .await?;
+ test((
+ "((so)((many) go#[o|]#d (text))(here))",
+ "2mim",
+ "(#[(so)((many) good (text))(here)|]#)",
+ ))
+ .await?;
+
+ // Works with mixed braces
+ test((
+ "(so [many {go#[o|]#d} text] here)",
+ "mim",
+ "(so [many {#[good|]#} text] here)",
+ ))
+ .await?;
+ test((
+ "(so [many {go#[o|]#d} text] here)",
+ "2mim",
+ "(so [#[many {good} text|]#] here)",
+ ))
+ .await?;
+ test((
+ "(so [many {go#[o|]#d} text] here)",
+ "3mim",
+ "(#[so [many {good} text] here|]#)",
+ ))
+ .await?;
+
+ // Selection direction is preserved
+ test((
+ "(so [many {go#[|od]#} text] here)",
+ "mim",
+ "(so [many {#[|good]#} text] here)",
+ ))
+ .await?;
+ test((
+ "(so [many {go#[|od]#} text] here)",
+ "2mim",
+ "(so [#[|many {good} text]#] here)",
+ ))
+ .await?;
+ test((
+ "(so [many {go#[|od]#} text] here)",
+ "3mim",
+ "(#[|so [many {good} text] here]#)",
+ ))
+ .await?;
+
+ // Only pairs outside of full selection range are considered
+ test((
+ "(so (many (go#[od) |]#text) here)",
+ "mim",
+ "(so (#[many (good) text|]#) here)",
+ ))
+ .await?;
+ test((
+ "(so (many#[ (go|]#od) text) here)",
+ "mim",
+ "(so (#[many (good) text|]#) here)",
+ ))
+ .await?;
+ test((
+ "(so#[ (many (go|]#od) text) here)",
+ "mim",
+ "(#[so (many (good) text) here|]#)",
+ ))
+ .await?;
+ test((
+ "(so (many (go#[od) text) |]#here)",
+ "mim",
+ "(#[so (many (good) text) here|]#)",
+ ))
+ .await?;
+
+ // Works with multiple cursors
+ test((
+ "(so (many (good) text) #[he|]#re\nso (many (good) text) #(|he)#re)",
+ "mim",
+ "(#[so (many (good) text) here\nso (many (good) text) here|]#)",
+ ))
+ .await?;
+
+ Ok(())
+}
+
+#[tokio::test(flavor = "multi_thread")]
+async fn surround_around_pair() -> anyhow::Result<()> {
+ // Works at first character of buffer
+ // TODO: Adjust test when opening pair failure is fixed
+ test(("#[(|]#something)", "mam", "#[(|]#something)")).await?;
+
+ // Inside a valid pair selects pair
+ test(("some (#[t|]#ext) here", "mam", "some #[(text)|]# here")).await?;
+
+ // On pair character selects pair
+ // TODO: Opening pair character is a known failure case that needs addressing
+ // test(("some #[(|]#text) here", "mam", "some #[(text)|]# here")).await?;
+ test(("some (text#[)|]# here", "mam", "some #[(text)|]# here")).await?;
+
+ // No valid pair does nothing
+ test(("so#[m|]#e (text) here", "mam", "so#[m|]#e (text) here")).await?;
+
+ // Count skips to outer pairs
+ test((
+ "(so (many (go#[o|]#d) text) here)",
+ "1mam",
+ "(so (many #[(good)|]# text) here)",
+ ))
+ .await?;
+ test((
+ "(so (many (go#[o|]#d) text) here)",
+ "2mam",
+ "(so #[(many (good) text)|]# here)",
+ ))
+ .await?;
+ test((
+ "(so (many (go#[o|]#d) text) here)",
+ "3mam",
+ "#[(so (many (good) text) here)|]#",
+ ))
+ .await?;
+
+ // Matching pairs outside selection don't match
+ test((
+ "((so)((many) go#[o|]#d (text))(here))",
+ "mam",
+ "((so)#[((many) good (text))|]#(here))",
+ ))
+ .await?;
+ test((
+ "((so)((many) go#[o|]#d (text))(here))",
+ "2mam",
+ "#[((so)((many) good (text))(here))|]#",
+ ))
+ .await?;
+
+ // Works with mixed braces
+ test((
+ "(so [many {go#[o|]#d} text] here)",
+ "mam",
+ "(so [many #[{good}|]# text] here)",
+ ))
+ .await?;
+ test((
+ "(so [many {go#[o|]#d} text] here)",
+ "2mam",
+ "(so #[[many {good} text]|]# here)",
+ ))
+ .await?;
+ test((
+ "(so [many {go#[o|]#d} text] here)",
+ "3mam",
+ "#[(so [many {good} text] here)|]#",
+ ))
+ .await?;
+
+ // Selection direction is preserved
+ test((
+ "(so [many {go#[|od]#} text] here)",
+ "mam",
+ "(so [many #[|{good}]# text] here)",
+ ))
+ .await?;
+ test((
+ "(so [many {go#[|od]#} text] here)",
+ "2mam",
+ "(so #[|[many {good} text]]# here)",
+ ))
+ .await?;
+ test((
+ "(so [many {go#[|od]#} text] here)",
+ "3mam",
+ "#[|(so [many {good} text] here)]#",
+ ))
+ .await?;
+
+ // Only pairs outside of full selection range are considered
+ test((
+ "(so (many (go#[od) |]#text) here)",
+ "mam",
+ "(so #[(many (good) text)|]# here)",
+ ))
+ .await?;
+ test((
+ "(so (many#[ (go|]#od) text) here)",
+ "mam",
+ "(so #[(many (good) text)|]# here)",
+ ))
+ .await?;
+ test((
+ "(so#[ (many (go|]#od) text) here)",
+ "mam",
+ "#[(so (many (good) text) here)|]#",
+ ))
+ .await?;
+ test((
+ "(so (many (go#[od) text) |]#here)",
+ "mam",
+ "#[(so (many (good) text) here)|]#",
+ ))
+ .await?;
+
+ // Works with multiple cursors
+ test((
+ "(so (many (good) text) #[he|]#re\nso (many (good) text) #(|he)#re)",
+ "mam",
+ "#[(so (many (good) text) here\nso (many (good) text) here)|]#",
+ ))
+ .await?;
+
+ Ok(())
+}
+
/// Ensure the very initial cursor in an opened file is the width of
/// the first grapheme
#[tokio::test(flavor = "multi_thread")]