diff options
author | Daniel S Poulin | 2023-02-10 19:52:57 +0000 |
---|---|---|
committer | GitHub | 2023-02-10 19:52:57 +0000 |
commit | 6929a12f291fa5dee50cde9c89845b206b7333fd (patch) | |
tree | 2dae3acd1ff9064db957f504da52afb41564a613 /helix-term/tests/test | |
parent | af1157f37c04e158b96f3e2da7c641356b2219dc (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/test')
-rw-r--r-- | helix-term/tests/test/movement.rs | 301 |
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")] |