vscode-modaledit icon indicating copy to clipboard operation
vscode-modaledit copied to clipboard

selectBetween: add multi-cursor support and Unicode flag

Open GoodDingo opened this issue 3 months ago • 1 comments

Multi-cursor support for modaledit.selectBetween

This PR enhances the modaledit.selectBetween command with two nice improvements:

  1. Multi-cursor support - Processes each cursor independently within its own line scope
  2. Unicode flag - Enables full Unicode regex support including property escapes like \p{L}, \p{Emoji}, etc.

Breaking Changes

None. Both new parameters are optional and default to backward-compatible values.

Example

# text below, "¦" marks 3 cursors

"q¦uote(příliš-žluťoučký-kůň)/a/b/c#tag.v2",
"quote(¦Mitä-kuuluu-kukkuluuruu?)/@xyz/$var#tag.v2",
"opt:quote(it-just-works-o¦n-multiline)",
"c i f": [
    "modaledit.cancelMultipleSelections",
    {
        "command": "modaledit.selectBetween",
        "args": "{ from: '[^\\\\p\\{L\\}_.:@#$%&*()+/!?-]', to: '[^\\\\p{L}\\\\p{N}_.:@#$%&*()+/!?-]', regex: true, unicode: true, inclusive: __rkeys[1] == 'a' }"
    }
]

With multi-cursor on, I can do cif operation that "does the right thing" and results in


"¦",
"¦",
"¦",
Rationale...

Rationale

Multi-Cursor Support

Previously, selectBetween only processed the primary cursor and discarded all other cursors, which was inconsistent with VS Code's multi-cursor philosophy and other ModalEdit commands. This limitation made the command unusable in multi-cursor workflows.

Key design decisions:

  • Each cursor operates independently within its own line scope (when docScope is false)
  • All cursors remain active after command execution
  • When docScope: true is used, falls back to single-cursor mode for predictable document-wide searches
  • Follows the same pattern as highlightMatches() (commands.ts:758-837)

Unicode Flag

The standard JavaScript regex engine doesn't support Unicode property escapes by default. Without the u flag, patterns like \p{L} (any Unicode letter) fail, making it impossible to properly handle:

  • International text (Czech: příliš žluťoučký kůň, Japanese: こんにちは, Arabic: مرحبا)
  • Emoji and special Unicode characters
  • Modern text processing requirements

Implementation:

  • Added optional unicode: boolean parameter to SelectBetweenArgs interface
  • Centralized flag construction in buildRegexFlags() helper (commands.ts:1057-1062)
  • Defaults to false for backward compatibility

Examples

Multi-Cursor Example

Select word at each cursor position across multiple lines:

{
    "command": "modaledit.selectBetween",
    "args": {
        "from": "\\W",
        "to": "\\W",
        "regex": true
    }
}

With cursors on lines containing "hello world", "foo bar", and "test case", this will select "hello", "foo", and "test" simultaneously.

Unicode Example

Select Unicode words (any sequence of Unicode letters) using property escapes:

{
    "command": "modaledit.selectBetween",
    "args": {
        "from": "[^\\\\p\\{L\\}_.:@#$%&*()+/!?-]",
        "to": "[^\\\\p\\{L\\}_.:@#$%&*()+/!?-]",
        "regex": true,
        "unicode": true
    }
}

This works correctly with international text like:

  • Czech: příliš-žluťoučký-kůň
  • Emoji: 🎉 celebration 🎊
  • Mixed scripts: hello世界мир

Without the unicode flag, \p{L} would be treated as literal characters and fail to match.

GoodDingo avatar Nov 25 '25 21:11 GoodDingo

Split to 2 commits (second is generated HTML, but there are some weird <span> diffs, not sure if I did it correctly...

GoodDingo avatar Nov 25 '25 22:11 GoodDingo