vim: Update anyquotes and anybrackets to behave like mini.ai plugin (#24167)
### Overview This PR improves the existing [mini.ai‐like](https://github.com/echasnovski/mini.ai) text-object logic for both “AnyQuotes” (quotes) and “AnyBrackets” (brackets) by adding a multi‐line fallback. The first pass searches only the current line for a best match (cover or next); if none are found, we do a multi‐line pass. This preserves mini.ai's usual “line priority” while ensuring we can detect pairs that start on one line and end on another. ### What Changed 1. Brackets - Line-based pass uses `gather_line_brackets(map, caret.row()) `to find bracket pairs `((), [], {}, <>) `on the caret’s line. - If that fails, we call `gather_brackets_multiline(map)` to single‐pass scan the entire buffer, collecting bracket pairs that might span multiple lines. - Finally, we apply the mini.ai “**cover or next**” logic (`pick_best_range`) to choose the best. 2. Quotes - Similar line-based pass with `gather_line_quotes(map, caret.row())`. - If no local quotes found, we do a multi‐line fallback with `gather_quotes_multiline(map)`, building a big string for the whole buffer and using naive regex for "...", '...', and `...`. - Also preserves “inner vs. outer” logic: - For inner (e.g. `ciq`), we skip bounding quotes or brackets if the range is at least 2 characters wide. - For outer (`caq`), we return the entire range. 3. Shared “`finalize`” helpers - `finalize_bracket_range` and `finalize_quote_range` handle the “inner” skip‐chars vs. “outer” logic. - Both rely on the same “line first, then full fallback” approach. ### Why This Matters - **Old Behavior**: If you had multi‐line brackets { ... } or multi‐line quotes spanning multiple lines, they weren’t found at all, since we only scanned line by line. That made text objects like ci{ or ciq fail in multi-line scenarios. - **New Behavior**: We still do a quick line pass (for user‐friendly “line priority”), but now if that fails, we do a single‐pass approach across the entire buffer. This detects multi‐line pairs and maintains mini.ai’s “cover‐or‐next” picking logic. ### Example Use Cases - **Curly braces:** e.g., opening { on line 10, closing } on line 15 → previously missed; now recognized. - **Multi‐line quotes**: e.g., "'Line 1\nLine 2', no longer missed. We do gather_quotes_multiline with a naive regex matching across newlines. ### Tests - Updated and expanded coverage in: - test_anyquotes_object: - Includes a multi-line '...' test case. - E.g. 'first' false\n<caret>string 'second' → ensuring we detect multi‐line quotes. - test_anybrackets_object: - Verifies line‐based priority but also multi‐line bracket detection. - E.g., an open bracket ( on line 3, close ) on line 5, which used to fail. ### Limitations / Future Enhancements - **Escaping**: The current approach for quotes is naive and doesn’t handle escape sequences (like \") or advanced parser logic. For deeper correctness, we’ll need more advanced logic, this is also not supported in the original mini.ai plugin so it is a known issue that won't be attended for now. ### Important Notes - Fix for the bug: https://github.com/zed-industries/zed/issues/23889 this PR addresses that bug specifically for the AnyQuotes text object. Note that the issue still remains in the built-in motions (ci', ci", ci`). - Caret Position Differences: The caret position now slightly deviates from Vim’s default behavior. This is intentional. I aim to closely mimic the mini.ai plugin. Because these text objects are optional (configurable via vim.json), this adjusted behavior is considered acceptable and in my opinion the new behavior is better and it should be the default in vim. Please review the new tests for details and context. - Improved Special Cases: I’ve also refined how “false strings” in the middle and certain curly-bracket scenarios are handled. The test suite reflects these improvements, resulting in a more seamless coding experience overall. ### References: - Mini.AI plugin in nvim: https://github.com/echasnovski/mini.ai Thank you for reviewing these changes! Release Notes: - Improve logic of aq, iq, ab and ib motions to work more like mini.ai plugin
This commit is contained in:
parent
a99696b95f
commit
e068c7b4b4
14 changed files with 323 additions and 80 deletions
|
@ -1,3 +1,6 @@
|
|||
("(" @open ")" @close)
|
||||
("[" @open "]" @close)
|
||||
("{" @open "}" @close)
|
||||
("\"" @open "\"" @close)
|
||||
("`" @open "`" @close)
|
||||
((raw_string) @open @close)
|
||||
|
|
|
@ -2,3 +2,4 @@
|
|||
("[" @open "]" @close)
|
||||
("{" @open "}" @close)
|
||||
("\"" @open "\"" @close)
|
||||
("'" @open "'" @close)
|
||||
|
|
|
@ -2,3 +2,4 @@
|
|||
("[" @open "]" @close)
|
||||
("{" @open "}" @close)
|
||||
("\"" @open "\"" @close)
|
||||
("'" @open "'" @close)
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
("(" @open ")" @close)
|
||||
("[" @open "]" @close)
|
||||
("{" @open "}" @close)
|
||||
("\"" @open "\"" @close)
|
||||
("'" @open "'" @close)
|
||||
|
|
|
@ -2,3 +2,5 @@
|
|||
("[" @open "]" @close)
|
||||
("{" @open "}" @close)
|
||||
("\"" @open "\"" @close)
|
||||
("`" @open "`" @close)
|
||||
((rune_literal) @open @close)
|
||||
|
|
|
@ -3,3 +3,5 @@
|
|||
("{" @open "}" @close)
|
||||
("<" @open ">" @close)
|
||||
("\"" @open "\"" @close)
|
||||
("'" @open "'" @close)
|
||||
("`" @open "`" @close)
|
||||
|
|
7
crates/languages/src/markdown/brackets.scm
Normal file
7
crates/languages/src/markdown/brackets.scm
Normal file
|
@ -0,0 +1,7 @@
|
|||
("(" @open ")" @close)
|
||||
("[" @open "]" @close)
|
||||
("{" @open "}" @close)
|
||||
("\"" @open "\"" @close)
|
||||
("`" @open "`" @close)
|
||||
("'" @open "'" @close)
|
||||
((fenced_code_block_delimiter) @open (fenced_code_block_delimiter) @close)
|
|
@ -1,3 +1,4 @@
|
|||
("(" @open ")" @close)
|
||||
("[" @open "]" @close)
|
||||
("{" @open "}" @close)
|
||||
((string_start) @open (string_end) @close)
|
||||
|
|
|
@ -4,3 +4,4 @@
|
|||
("<" @open ">" @close)
|
||||
("\"" @open "\"" @close)
|
||||
(closure_parameters "|" @open "|" @close)
|
||||
("'" @open "'" @close)
|
||||
|
|
|
@ -5,3 +5,5 @@
|
|||
("<" @open "/>" @close)
|
||||
("</" @open ">" @close)
|
||||
("\"" @open "\"" @close)
|
||||
("'" @open "'" @close)
|
||||
("`" @open "`" @close)
|
||||
|
|
|
@ -3,3 +3,5 @@
|
|||
("{" @open "}" @close)
|
||||
("<" @open ">" @close)
|
||||
("\"" @open "\"" @close)
|
||||
("'" @open "'" @close)
|
||||
("`" @open "`" @close)
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
("[" @open "]" @close)
|
||||
("{" @open "}" @close)
|
||||
("\"" @open "\"" @close)
|
||||
("'" @open "'" @close)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue