summaryrefslogtreecommitdiff
path: root/test/hxcases
diff options
context:
space:
mode:
authorGabriel Schneider <[email protected]>2026-07-31 05:04:26 -0300
committerGabriel Schneider <[email protected]>2026-08-01 15:02:08 -0300
commit5bf8d6dd077517270377e5d8551108ecf252374f (patch)
treec7783fa9fc133980d3d6fff0129e8de5a1b43601 /test/hxcases
parenteefac04995ffad847a4098f16d2e82ccab16438b (diff)
downloadpardes-5bf8d6dd077517270377e5d8551108ecf252374f.tar.gz
pardes-5bf8d6dd077517270377e5d8551108ecf252374f.zip
multiple cursors, regex selection, and Ctrl-c comments
The primary cursor stays exactly where it was — cur_row/cur_col plus vsel — and sels[] holds helix's OTHER ranges. That split is why nothing moved at one cursor: with nsel == 0 not one line of the existing motion, operator, render or mouse code takes a different branch, which is what protects 800 differential cases and 67 goldens. paneRanges/setPaneRanges are the whole list; setPaneRanges IS helix's Selection::new (min width 1, sorted, overlaps merged, primary follows its range through a merge). An ordinary key runs the single-selection handler once per range, visited last-first so an edit never disturbs a range still waiting, and each finished pass is remembered as a distance from the END of the text, which an earlier edit cannot move — helix's change mapping without a change map. pushUndo fires once per keystroke, yanks accumulate, and a builtin acts from the primary and stops the replay, which also closes the use-after-free window if it frees the pane. s and S reuse the / prompt wholesale rather than growing a second one: the pattern is typed into the tag tail, and every keystroke re-runs the match from the selection the prompt opened on, so the preview is live and Esc is just the empty pattern. mvzr does runtime patterns — a bytecode VM in a fixed-size struct with no allocator — with 64 ops and 8 char classes per pattern, no case-insensitive flag (helix's smart case is done by folding a scratch copy), no captures, no multi-line anchors. The last two are the two waivers. Ctrl-c is a whole-list key and not a per-cursor replay, because helix decides comment-vs-uncomment ONCE for the whole selection; replaying it would take that decision n times. Comment tokens are a table in config.zig keyed on the same extension syntax.zig picks grammars by. Found and fixed a pre-existing single-cursor bug on the way: la<bs><esc> left the cursor one cell before where the append began. helix's restore_cursor can never walk past the origin; ours backed up unconditionally. hxdiff was green before AND after — the old one-selection contract could not see it. hxdiff 360 -> 481 cases, hxparity 440 -> 561, all goldens from real helix; the harness contract now reports every range and its primary, omitted when there is one, so 359 of the 360 old goldens are byte-identical. The one that moved is o-count: helix's 2o really does leave two cursors and could not say so before.
Diffstat (limited to 'test/hxcases')
-rw-r--r--test/hxcases/cases.jsonl121
-rw-r--r--test/hxcases/goldens.jsonl123
-rw-r--r--test/hxcases/parity-waivers.jsonl3
-rw-r--r--test/hxcases/waivers.jsonl4
4 files changed, 250 insertions, 1 deletions
diff --git a/test/hxcases/cases.jsonl b/test/hxcases/cases.jsonl
index 386013bf..b0a3aad4 100644
--- a/test/hxcases/cases.jsonl
+++ b/test/hxcases/cases.jsonl
@@ -358,3 +358,124 @@
{"name": "ins-arrows", "pane": "file", "text": "abc\ndef\n", "keys": "i<down><right>x<esc>"}
{"name": "ins-tab-col0", "pane": "file", "text": "ab\n", "keys": "i<tab><esc>"}
{"name": "ins-tab-mid", "pane": "file", "text": "ab\n", "keys": "li<tab><esc>"}
+{"name": "msel-C-basic", "pane": "file", "text": "aaa\nbbb\nccc\n", "keys": "lC"}
+{"name": "msel-C-basic-tty", "pane": "tty", "text": "aaa\nbbb\nccc\n", "keys": "lC"}
+{"name": "msel-C-count", "pane": "file", "text": "aaa\nbbb\nccc\nddd\n", "keys": "2C"}
+{"name": "msel-C-count-tty", "pane": "tty", "text": "aaa\nbbb\nccc\nddd\n", "keys": "2C"}
+{"name": "msel-C-skips-short", "pane": "file", "text": "abcdef\nab\nabcdef\n", "keys": "4lC"}
+{"name": "msel-C-stops-at-eof", "pane": "file", "text": "aa\nbb\n", "keys": "CCC"}
+{"name": "msel-C-of-selection", "pane": "file", "text": "abcd\nabcd\nabcd\n", "keys": "vllC"}
+{"name": "msel-C-above", "pane": "file", "text": "aaa\nbbb\nccc\n", "keys": "jjl<A-C>"}
+{"name": "msel-C-above-tty", "pane": "tty", "text": "aaa\nbbb\nccc\n", "keys": "jjl<A-C>"}
+{"name": "msel-C-above-at-top", "pane": "file", "text": "aaa\nbbb\n", "keys": "<A-C>"}
+{"name": "msel-C-empty-line", "pane": "file", "text": "ab\n\ncd\n", "keys": "C"}
+{"name": "msel-move-l", "pane": "file", "text": "aaa\nbbb\nccc\n", "keys": "Cl"}
+{"name": "msel-move-l-tty", "pane": "tty", "text": "aaa\nbbb\nccc\n", "keys": "Cl"}
+{"name": "msel-move-jj", "pane": "file", "text": "aaaa\nbbbb\ncccc\ndddd\n", "keys": "2lCkk"}
+{"name": "msel-word", "pane": "file", "text": "one two\nsix seven\n", "keys": "Cw"}
+{"name": "msel-goto-line-end", "pane": "file", "text": "aaa\nbbbbb\n", "keys": "Cgl"}
+{"name": "msel-keep-primary", "pane": "file", "text": "aaa\nbbb\nccc\n", "keys": "CC,"}
+{"name": "msel-keep-primary-tty", "pane": "tty", "text": "aaa\nbbb\nccc\n", "keys": "CC,"}
+{"name": "msel-remove-primary", "pane": "file", "text": "aaa\nbbb\nccc\n", "keys": "CC<A-,>"}
+{"name": "msel-remove-primary-last", "pane": "file", "text": "aaa\nbbb\nccc\n", "keys": "CC)<A-,>"}
+{"name": "msel-rotate-fwd", "pane": "file", "text": "aaa\nbbb\nccc\n", "keys": "CC)"}
+{"name": "msel-rotate-fwd-tty", "pane": "tty", "text": "aaa\nbbb\nccc\n", "keys": "CC)"}
+{"name": "msel-rotate-back", "pane": "file", "text": "aaa\nbbb\nccc\n", "keys": "CC("}
+{"name": "msel-rotate-wrap", "pane": "file", "text": "aaa\nbbb\n", "keys": "C))"}
+{"name": "msel-split-newline", "pane": "file", "text": "aa\nbb\ncc\n", "keys": "%<A-s>"}
+{"name": "msel-split-partial", "pane": "file", "text": "abcd\nefgh\n", "keys": "vjl<A-s>"}
+{"name": "msel-split-partial-tty", "pane": "tty", "text": "abcd\nefgh\n", "keys": "vjl<A-s>"}
+{"name": "msel-merge", "pane": "file", "text": "aaa\nbbb\nccc\n", "keys": "CC<A-minus>"}
+{"name": "msel-merge-consecutive", "pane": "file", "text": "aa\nbb\ncc\n", "keys": "xC<A-_>"}
+{"name": "msel-trim", "pane": "file", "text": " ab \n", "keys": "%_"}
+{"name": "msel-trim-all-ws", "pane": "file", "text": " \n", "keys": "%_"}
+{"name": "msel-trim-multi", "pane": "file", "text": " ab \n cd \n", "keys": "x<A-x>C_"}
+{"name": "msel-insert", "pane": "file", "text": "aa\nbb\n", "keys": "Cix<esc>"}
+{"name": "msel-insert-tty", "pane": "tty", "text": "aa\nbb\n", "keys": "Cix<esc>"}
+{"name": "msel-append", "pane": "file", "text": "aa\nbb\n", "keys": "Caz<esc>"}
+{"name": "msel-insert-two-chars", "pane": "file", "text": "aa\nbb\ncc\n", "keys": "2Cixy<esc>"}
+{"name": "msel-delete", "pane": "file", "text": "abc\nabc\n", "keys": "Cd"}
+{"name": "msel-delete-tty", "pane": "tty", "text": "abc\nabc\n", "keys": "Cd"}
+{"name": "msel-delete-selection", "pane": "file", "text": "abcd\nabcd\n", "keys": "vlCd"}
+{"name": "msel-change", "pane": "file", "text": "abc\nabc\n", "keys": "Ccz<esc>"}
+{"name": "msel-switch-case", "pane": "file", "text": "abc\nabc\n", "keys": "C~"}
+{"name": "msel-switch-case-tty", "pane": "tty", "text": "abc\nabc\n", "keys": "C~"}
+{"name": "msel-uppercase", "pane": "file", "text": "abc\nabc\n", "keys": "vlC<A-`>"}
+{"name": "msel-indent", "pane": "file", "text": "aa\nbb\n", "keys": "C<gt>"}
+{"name": "msel-replace-char", "pane": "file", "text": "abc\nabc\n", "keys": "Crz"}
+{"name": "msel-undo", "pane": "file", "text": "abc\nabc\n", "keys": "Cdu"}
+{"name": "msel-open-below", "pane": "file", "text": "aa\nbb\n", "keys": "Coz<esc>"}
+{"name": "msel-line-select", "pane": "file", "text": "aa\nbb\ncc\n", "keys": "Cx"}
+{"name": "msel-collapse", "pane": "file", "text": "abcd\nabcd\n", "keys": "vllC;"}
+{"name": "msel-flip", "pane": "file", "text": "abcd\nabcd\n", "keys": "vllC<A-;>"}
+{"name": "msel-yank-paste", "pane": "file", "text": "ab\ncd\n", "keys": "Cyp"}
+{"name": "msel-esc-keeps", "pane": "file", "text": "aa\nbb\n", "keys": "C<esc>"}
+{"name": "msel-select-mode", "pane": "file", "text": "abcd\nabcd\n", "keys": "Cvl"}
+{"name": "msel-open-count", "pane": "file", "text": "ab\n", "keys": "2O"}
+{"name": "msel-backspace", "pane": "file", "text": "abc\nabc\n", "keys": "Cla<backspace><esc>"}
+{"name": "msel-backspace-tty", "pane": "tty", "text": "abc\nabc\n", "keys": "Cla<backspace><esc>"}
+{"name": "sel-regex-basic", "pane": "file", "text": "alpha beta alpha\n", "keys": "%sa<ret>"}
+{"name": "sel-regex-basic-tty", "pane": "tty", "text": "alpha beta alpha\n", "keys": "%sa<ret>"}
+{"name": "sel-regex-word", "pane": "file", "text": "alpha beta alpha\n", "keys": "%salpha<ret>"}
+{"name": "sel-regex-class", "pane": "file", "text": "a1b22c333\n", "keys": "%s[0-9]+<ret>"}
+{"name": "sel-regex-class-tty", "pane": "tty", "text": "a1b22c333\n", "keys": "%s[0-9]+<ret>"}
+{"name": "sel-regex-alt", "pane": "file", "text": "cat dog cat\n", "keys": "%scat|dog<ret>"}
+{"name": "sel-regex-plus", "pane": "file", "text": "aa b aaa\n", "keys": "%sa+<ret>"}
+{"name": "sel-regex-star-empty", "pane": "file", "text": "ab\n", "keys": "%sx*<ret>"}
+{"name": "sel-regex-nomatch", "pane": "file", "text": "alpha beta\n", "keys": "%szzz<ret>"}
+{"name": "sel-regex-esc", "pane": "file", "text": "alpha beta alpha\n", "keys": "%sa<esc>"}
+{"name": "sel-regex-empty", "pane": "file", "text": "abc\n", "keys": "%s<ret>"}
+{"name": "sel-regex-invalid", "pane": "file", "text": "abc\n", "keys": "%s[<ret>"}
+{"name": "sel-regex-within-sels", "pane": "file", "text": "aXa\nbXb\n", "keys": "xxsX<ret>"}
+{"name": "sel-regex-within-sels-tty", "pane": "tty", "text": "aXa\nbXb\n", "keys": "xxsX<ret>"}
+{"name": "sel-regex-at-cursors", "pane": "file", "text": "foo bar\nfoo baz\n", "keys": "xxsfoo<ret>"}
+{"name": "sel-regex-narrow", "pane": "file", "text": "alpha beta alpha\n", "keys": "%salpha<ret>sa<ret>"}
+{"name": "sel-regex-select-mode", "pane": "file", "text": "alpha beta\n", "keys": "v5lsa<ret>"}
+{"name": "sel-regex-multiline", "pane": "file", "text": "one\ntwo\nthree\n", "keys": "%so<ret>"}
+{"name": "sel-regex-smart-case", "pane": "file", "text": "Alpha alpha ALPHA\n", "keys": "%salpha<ret>"}
+{"name": "sel-regex-cased", "pane": "file", "text": "Alpha alpha ALPHA\n", "keys": "%sAlpha<ret>"}
+{"name": "sel-regex-boundary", "pane": "file", "text": "cat cats\n", "keys": "%s\\bcat\\b<ret>"}
+{"name": "sel-regex-whole", "pane": "file", "text": "abc\n", "keys": "%sabc<ret>"}
+{"name": "sel-regex-then-motion", "pane": "file", "text": "foo bar foo baz\n", "keys": "%sfoo<ret>w"}
+{"name": "sel-regex-then-delete", "pane": "file", "text": "a1b2c3\n", "keys": "%s[0-9]<ret>d"}
+{"name": "sel-regex-dot-newline", "pane": "file", "text": "ab\n", "keys": "%s.<ret>"}
+{"name": "sel-regex-caret", "pane": "file", "text": "ab\nab\n", "keys": "%s^a<ret>"}
+{"name": "split-regex-comma", "pane": "file", "text": "a,b,c\n", "keys": "%S,<ret>"}
+{"name": "split-regex-comma-tty", "pane": "tty", "text": "a,b,c\n", "keys": "%S,<ret>"}
+{"name": "split-regex-lead", "pane": "file", "text": ",a,b\n", "keys": "%S,<ret>"}
+{"name": "split-regex-trail", "pane": "file", "text": "a,b,\n", "keys": "%S,<ret>"}
+{"name": "split-regex-adjacent", "pane": "file", "text": "a,,b\n", "keys": "%S,<ret>"}
+{"name": "split-regex-ws", "pane": "file", "text": "one two three\n", "keys": "%S\\s+<ret>"}
+{"name": "split-regex-ws-tty", "pane": "tty", "text": "one two three\n", "keys": "%S\\s+<ret>"}
+{"name": "split-regex-nomatch", "pane": "file", "text": "abc\n", "keys": "%Sz<ret>"}
+{"name": "split-regex-newline", "pane": "file", "text": "one\ntwo\nthree\n", "keys": "%S\\n<ret>"}
+{"name": "split-regex-esc", "pane": "file", "text": "a,b,c\n", "keys": "%S,<esc>"}
+{"name": "split-regex-within-sels", "pane": "file", "text": "aXa\nbXb\n", "keys": "xxSX<ret>"}
+{"name": "split-regex-end", "pane": "file", "text": "abc\n", "keys": "%Sc<ret>"}
+{"name": "comment-line", "pane": "file", "text": "alpha\nbeta\n", "keys": "<C-c>"}
+{"name": "comment-toggle-back", "pane": "file", "text": "alpha\nbeta\n", "keys": "<C-c><C-c>"}
+{"name": "comment-selection", "pane": "file", "text": "alpha\nbeta\ngamma\n", "keys": "xx<C-c>"}
+{"name": "comment-indent", "pane": "file", "text": " alpha\n beta\n", "keys": "%<C-c>"}
+{"name": "comment-indent-round-trip", "pane": "file", "text": " alpha\n beta\n", "keys": "%<C-c>%<C-c>"}
+{"name": "comment-blank-skipped", "pane": "file", "text": "alpha\n\nbeta\n", "keys": "%<C-c>"}
+{"name": "comment-partial", "pane": "file", "text": "# alpha\nbeta\ngamma\n", "keys": "%<C-c>"}
+{"name": "comment-uncomment", "pane": "file", "text": "# alpha\n# beta\n", "keys": "%<C-c>"}
+{"name": "comment-margin0", "pane": "file", "text": "#alpha\n# beta\n", "keys": "%<C-c>"}
+{"name": "comment-token-only", "pane": "file", "text": "#\n#\n", "keys": "%<C-c>"}
+{"name": "comment-uncomment-deep", "pane": "file", "text": "# alpha\n # beta\n", "keys": "%<C-c>"}
+{"name": "comment-tab-indent", "pane": "file", "text": "\talpha\n\tbeta\n", "keys": "%<C-c>"}
+{"name": "comment-other-token", "pane": "file", "text": "// alpha\n// beta\n", "keys": "%<C-c>"}
+{"name": "comment-noeol", "pane": "file", "text": "alpha", "keys": "<C-c>"}
+{"name": "comment-empty", "pane": "file", "text": "\n", "keys": "<C-c>"}
+{"name": "comment-only-blank", "pane": "file", "text": " \n\t\n", "keys": "%<C-c>"}
+{"name": "comment-select-mode", "pane": "file", "text": "alpha\nbeta\n", "keys": "vj<C-c>"}
+{"name": "comment-count-ignored", "pane": "file", "text": "alpha\nbeta\ngamma\n", "keys": "3<C-c>"}
+{"name": "comment-undo", "pane": "file", "text": "alpha\nbeta\n", "keys": "%<C-c>u"}
+{"name": "comment-multi-cursor", "pane": "file", "text": "alpha\nbeta\ngamma\n", "keys": "C<C-c>"}
+{"name": "comment-same-line-cursors", "pane": "file", "text": "alpha beta\n", "keys": "wC<C-c>"}
+{"name": "comment-cursor-gap", "pane": "file", "text": "a\nb\nc\nd\n", "keys": "2C<C-c>"}
+{"name": "comment-split-cursors", "pane": "file", "text": "alpha\nbeta\ngamma\n", "keys": "%<A-s><C-c>"}
+{"name": "comment-last-line", "pane": "file", "text": "alpha\nbeta\n", "keys": "jj<C-c>"}
+{"name": "comment-then-insert", "pane": "file", "text": "alpha\n", "keys": "<C-c>iz<esc>"}
+{"name": "comment-after-sel-regex", "pane": "file", "text": "alpha\nbeta\ngamma\n", "keys": "%sa<ret><C-c>"}
+{"name": "comment-after-split-regex", "pane": "file", "text": "a,b\nc,d\n", "keys": "%S,<ret><C-c>"}
diff --git a/test/hxcases/goldens.jsonl b/test/hxcases/goldens.jsonl
index baa45d34..eee7294b 100644
--- a/test/hxcases/goldens.jsonl
+++ b/test/hxcases/goldens.jsonl
@@ -323,7 +323,7 @@
{"name":"o-basic","text":"ab\nx\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}}
{"name":"o-copies-indent-level","text":" foo\n \n","mode":"insert","cursor":{"row":1,"col":4},"anchor":{"row":1,"col":4}}
{"name":"o-partial-indent-drops","text":" foo\n\n","mode":"insert","cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}}
-{"name":"o-count","text":"ab\n\n\n","mode":"normal","cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}}
+{"name":"o-count","text":"ab\n\n\n","mode":"normal","cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}},{"cursor":{"row":2,"col":0},"anchor":{"row":2,"col":0}}],"primary":0}
{"name":"O-basic","text":"aa\nx\nbb\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}}
{"name":"O-copies-indent","text":" \n foo\n","mode":"insert","cursor":{"row":0,"col":4},"anchor":{"row":0,"col":4}}
{"name":"i-type-esc","text":"hello alpha\n","mode":"normal","cursor":{"row":0,"col":6},"anchor":{"row":0,"col":6}}
@@ -358,3 +358,124 @@
{"name":"ins-arrows","text":"abc\ndxef\n","mode":"normal","cursor":{"row":1,"col":2},"anchor":{"row":1,"col":2}}
{"name":"ins-tab-col0","text":" ab\n","mode":"normal","cursor":{"row":0,"col":4},"anchor":{"row":0,"col":4}}
{"name":"ins-tab-mid","text":"a b\n","mode":"normal","cursor":{"row":0,"col":4},"anchor":{"row":0,"col":4}}
+{"name":"msel-C-basic","text":"aaa\nbbb\nccc\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}}],"primary":1}
+{"name":"msel-C-basic-tty","text":"aaa\nbbb\nccc\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}}],"primary":1}
+{"name":"msel-C-count","text":"aaa\nbbb\nccc\nddd\n","mode":"normal","cursor":{"row":2,"col":0},"anchor":{"row":2,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}},{"cursor":{"row":2,"col":0},"anchor":{"row":2,"col":0}}],"primary":2}
+{"name":"msel-C-count-tty","text":"aaa\nbbb\nccc\nddd\n","mode":"normal","cursor":{"row":2,"col":0},"anchor":{"row":2,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}},{"cursor":{"row":2,"col":0},"anchor":{"row":2,"col":0}}],"primary":2}
+{"name":"msel-C-skips-short","text":"abcdef\nab\nabcdef\n","mode":"normal","cursor":{"row":2,"col":4},"anchor":{"row":2,"col":4},"sels":[{"cursor":{"row":0,"col":4},"anchor":{"row":0,"col":4}},{"cursor":{"row":2,"col":4},"anchor":{"row":2,"col":4}}],"primary":1}
+{"name":"msel-C-stops-at-eof","text":"aa\nbb\n","mode":"normal","cursor":{"row":2,"col":0},"anchor":{"row":2,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}},{"cursor":{"row":2,"col":0},"anchor":{"row":2,"col":0}}],"primary":2}
+{"name":"msel-C-of-selection","text":"abcd\nabcd\nabcd\n","mode":"select","cursor":{"row":1,"col":2},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":2},"anchor":{"row":1,"col":0}}],"primary":1}
+{"name":"msel-C-above","text":"aaa\nbbb\nccc\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1},"sels":[{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}},{"cursor":{"row":2,"col":1},"anchor":{"row":2,"col":1}}],"primary":0}
+{"name":"msel-C-above-tty","text":"aaa\nbbb\nccc\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1},"sels":[{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}},{"cursor":{"row":2,"col":1},"anchor":{"row":2,"col":1}}],"primary":0}
+{"name":"msel-C-above-at-top","text":"aaa\nbbb\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}}
+{"name":"msel-C-empty-line","text":"ab\n\ncd\n","mode":"normal","cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}}],"primary":1}
+{"name":"msel-move-l","text":"aaa\nbbb\nccc\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}}],"primary":1}
+{"name":"msel-move-l-tty","text":"aaa\nbbb\nccc\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}}],"primary":1}
+{"name":"msel-move-jj","text":"aaaa\nbbbb\ncccc\ndddd\n","mode":"normal","cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}}
+{"name":"msel-word","text":"one two\nsix seven\n","mode":"normal","cursor":{"row":1,"col":3},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":0,"col":3},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":3},"anchor":{"row":1,"col":0}}],"primary":1}
+{"name":"msel-goto-line-end","text":"aaa\nbbbbb\n","mode":"normal","cursor":{"row":1,"col":4},"anchor":{"row":1,"col":4},"sels":[{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}},{"cursor":{"row":1,"col":4},"anchor":{"row":1,"col":4}}],"primary":1}
+{"name":"msel-keep-primary","text":"aaa\nbbb\nccc\n","mode":"normal","cursor":{"row":2,"col":0},"anchor":{"row":2,"col":0}}
+{"name":"msel-keep-primary-tty","text":"aaa\nbbb\nccc\n","mode":"normal","cursor":{"row":2,"col":0},"anchor":{"row":2,"col":0}}
+{"name":"msel-remove-primary","text":"aaa\nbbb\nccc\n","mode":"normal","cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}}],"primary":1}
+{"name":"msel-remove-primary-last","text":"aaa\nbbb\nccc\n","mode":"normal","cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}},{"cursor":{"row":2,"col":0},"anchor":{"row":2,"col":0}}],"primary":0}
+{"name":"msel-rotate-fwd","text":"aaa\nbbb\nccc\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}},{"cursor":{"row":2,"col":0},"anchor":{"row":2,"col":0}}],"primary":0}
+{"name":"msel-rotate-fwd-tty","text":"aaa\nbbb\nccc\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}},{"cursor":{"row":2,"col":0},"anchor":{"row":2,"col":0}}],"primary":0}
+{"name":"msel-rotate-back","text":"aaa\nbbb\nccc\n","mode":"normal","cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}},{"cursor":{"row":2,"col":0},"anchor":{"row":2,"col":0}}],"primary":1}
+{"name":"msel-rotate-wrap","text":"aaa\nbbb\n","mode":"normal","cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}}],"primary":1}
+{"name":"msel-split-newline","text":"aa\nbb\ncc\n","mode":"normal","cursor":{"row":0,"col":1},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":0}},{"cursor":{"row":2,"col":1},"anchor":{"row":2,"col":0}}],"primary":0}
+{"name":"msel-split-partial","text":"abcd\nefgh\n","mode":"select","cursor":{"row":0,"col":3},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":3},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":0}}],"primary":0}
+{"name":"msel-split-partial-tty","text":"abcd\nefgh\n","mode":"select","cursor":{"row":0,"col":3},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":3},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":0}}],"primary":0}
+{"name":"msel-merge","text":"aaa\nbbb\nccc\n","mode":"normal","cursor":{"row":2,"col":0},"anchor":{"row":0,"col":0}}
+{"name":"msel-merge-consecutive","text":"aa\nbb\ncc\n","mode":"normal","cursor":{"row":1,"col":2},"anchor":{"row":0,"col":0}}
+{"name":"msel-trim","text":" ab \n","mode":"normal","cursor":{"row":0,"col":3},"anchor":{"row":0,"col":2}}
+{"name":"msel-trim-all-ws","text":" \n","mode":"normal","cursor":{"row":0,"col":3},"anchor":{"row":0,"col":3}}
+{"name":"msel-trim-multi","text":" ab \n cd \n","mode":"normal","cursor":{"row":1,"col":2},"anchor":{"row":1,"col":1},"sels":[{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":1}},{"cursor":{"row":1,"col":2},"anchor":{"row":1,"col":1}}],"primary":1}
+{"name":"msel-insert","text":"xaa\nxbb\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}}],"primary":1}
+{"name":"msel-insert-tty","text":"xaa\nxbb\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}}],"primary":1}
+{"name":"msel-append","text":"aza\nbzb\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":0}}],"primary":1}
+{"name":"msel-insert-two-chars","text":"xyaa\nxybb\nxycc\n","mode":"normal","cursor":{"row":2,"col":2},"anchor":{"row":2,"col":2},"sels":[{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}},{"cursor":{"row":1,"col":2},"anchor":{"row":1,"col":2}},{"cursor":{"row":2,"col":2},"anchor":{"row":2,"col":2}}],"primary":2}
+{"name":"msel-delete","text":"bc\nbc\n","mode":"normal","cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}}],"primary":1}
+{"name":"msel-delete-tty","text":"bc\nbc\n","mode":"normal","cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}}],"primary":1}
+{"name":"msel-delete-selection","text":"cd\ncd\n","mode":"normal","cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}}],"primary":1}
+{"name":"msel-change","text":"zbc\nzbc\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}}],"primary":1}
+{"name":"msel-switch-case","text":"Abc\nAbc\n","mode":"normal","cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}}],"primary":1}
+{"name":"msel-switch-case-tty","text":"Abc\nAbc\n","mode":"normal","cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}}],"primary":1}
+{"name":"msel-uppercase","text":"ABc\nABc\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":0}}],"primary":1}
+{"name":"msel-indent","text":" aa\n bb\n","mode":"normal","cursor":{"row":1,"col":4},"anchor":{"row":1,"col":4},"sels":[{"cursor":{"row":0,"col":4},"anchor":{"row":0,"col":4}},{"cursor":{"row":1,"col":4},"anchor":{"row":1,"col":4}}],"primary":1}
+{"name":"msel-replace-char","text":"zbc\nzbc\n","mode":"normal","cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}}],"primary":1}
+{"name":"msel-undo","text":"abc\nabc\n","mode":"normal","cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}}],"primary":1}
+{"name":"msel-open-below","text":"aa\nz\nbb\nz\n","mode":"normal","cursor":{"row":3,"col":1},"anchor":{"row":3,"col":1},"sels":[{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}},{"cursor":{"row":3,"col":1},"anchor":{"row":3,"col":1}}],"primary":1}
+{"name":"msel-line-select","text":"aa\nbb\ncc\n","mode":"normal","cursor":{"row":1,"col":2},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":2},"anchor":{"row":1,"col":0}}],"primary":1}
+{"name":"msel-collapse","text":"abcd\nabcd\n","mode":"select","cursor":{"row":1,"col":2},"anchor":{"row":1,"col":2},"sels":[{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}},{"cursor":{"row":1,"col":2},"anchor":{"row":1,"col":2}}],"primary":1}
+{"name":"msel-flip","text":"abcd\nabcd\n","mode":"select","cursor":{"row":1,"col":0},"anchor":{"row":1,"col":2},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":2}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":2}}],"primary":1}
+{"name":"msel-yank-paste","text":"aab\nccd\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}}],"primary":1}
+{"name":"msel-esc-keeps","text":"aa\nbb\n","mode":"normal","cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}}],"primary":1}
+{"name":"msel-select-mode","text":"abcd\nabcd\n","mode":"select","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":0},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":0}}],"primary":1}
+{"name":"msel-open-count","text":"\n\nab\n","mode":"insert","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}}],"primary":0}
+{"name":"msel-backspace","text":"ac\nac\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}}],"primary":1}
+{"name":"msel-backspace-tty","text":"ac\nac\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}}],"primary":1}
+{"name":"sel-regex-basic","text":"alpha beta alpha\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":0,"col":4},"anchor":{"row":0,"col":4}},{"cursor":{"row":0,"col":9},"anchor":{"row":0,"col":9}},{"cursor":{"row":0,"col":11},"anchor":{"row":0,"col":11}},{"cursor":{"row":0,"col":15},"anchor":{"row":0,"col":15}}],"primary":0}
+{"name":"sel-regex-basic-tty","text":"alpha beta alpha\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":0,"col":4},"anchor":{"row":0,"col":4}},{"cursor":{"row":0,"col":9},"anchor":{"row":0,"col":9}},{"cursor":{"row":0,"col":11},"anchor":{"row":0,"col":11}},{"cursor":{"row":0,"col":15},"anchor":{"row":0,"col":15}}],"primary":0}
+{"name":"sel-regex-word","text":"alpha beta alpha\n","mode":"normal","cursor":{"row":0,"col":4},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":4},"anchor":{"row":0,"col":0}},{"cursor":{"row":0,"col":15},"anchor":{"row":0,"col":11}}],"primary":0}
+{"name":"sel-regex-class","text":"a1b22c333\n","mode":"normal","cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":0,"col":4},"anchor":{"row":0,"col":3}},{"cursor":{"row":0,"col":8},"anchor":{"row":0,"col":6}}],"primary":0}
+{"name":"sel-regex-class-tty","text":"a1b22c333\n","mode":"normal","cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":0,"col":4},"anchor":{"row":0,"col":3}},{"cursor":{"row":0,"col":8},"anchor":{"row":0,"col":6}}],"primary":0}
+{"name":"sel-regex-alt","text":"cat dog cat\n","mode":"normal","cursor":{"row":0,"col":2},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":0}},{"cursor":{"row":0,"col":6},"anchor":{"row":0,"col":4}},{"cursor":{"row":0,"col":10},"anchor":{"row":0,"col":8}}],"primary":0}
+{"name":"sel-regex-plus","text":"aa b aaa\n","mode":"normal","cursor":{"row":0,"col":1},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":0}},{"cursor":{"row":0,"col":7},"anchor":{"row":0,"col":5}}],"primary":0}
+{"name":"sel-regex-star-empty","text":"ab\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}}],"primary":0}
+{"name":"sel-regex-nomatch","text":"alpha beta\n","mode":"normal","cursor":{"row":0,"col":10},"anchor":{"row":0,"col":0}}
+{"name":"sel-regex-esc","text":"alpha beta alpha\n","mode":"normal","cursor":{"row":0,"col":16},"anchor":{"row":0,"col":0}}
+{"name":"sel-regex-empty","text":"abc\n","mode":"normal","cursor":{"row":0,"col":3},"anchor":{"row":0,"col":0}}
+{"name":"sel-regex-invalid","text":"abc\n","mode":"normal","cursor":{"row":0,"col":3},"anchor":{"row":0,"col":0}}
+{"name":"sel-regex-within-sels","text":"aXa\nbXb\n","mode":"normal","cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}}],"primary":0}
+{"name":"sel-regex-within-sels-tty","text":"aXa\nbXb\n","mode":"normal","cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":1,"col":1},"anchor":{"row":1,"col":1}}],"primary":0}
+{"name":"sel-regex-at-cursors","text":"foo bar\nfoo baz\n","mode":"normal","cursor":{"row":0,"col":2},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":2},"anchor":{"row":1,"col":0}}],"primary":0}
+{"name":"sel-regex-narrow","text":"alpha beta alpha\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":0,"col":4},"anchor":{"row":0,"col":4}},{"cursor":{"row":0,"col":11},"anchor":{"row":0,"col":11}},{"cursor":{"row":0,"col":15},"anchor":{"row":0,"col":15}}],"primary":0}
+{"name":"sel-regex-select-mode","text":"alpha beta\n","mode":"select","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":0,"col":4},"anchor":{"row":0,"col":4}}],"primary":0}
+{"name":"sel-regex-multiline","text":"one\ntwo\nthree\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":2},"anchor":{"row":1,"col":2}}],"primary":0}
+{"name":"sel-regex-smart-case","text":"Alpha alpha ALPHA\n","mode":"normal","cursor":{"row":0,"col":4},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":4},"anchor":{"row":0,"col":0}},{"cursor":{"row":0,"col":10},"anchor":{"row":0,"col":6}},{"cursor":{"row":0,"col":16},"anchor":{"row":0,"col":12}}],"primary":0}
+{"name":"sel-regex-cased","text":"Alpha alpha ALPHA\n","mode":"normal","cursor":{"row":0,"col":4},"anchor":{"row":0,"col":0}}
+{"name":"sel-regex-boundary","text":"cat cats\n","mode":"normal","cursor":{"row":0,"col":2},"anchor":{"row":0,"col":0}}
+{"name":"sel-regex-whole","text":"abc\n","mode":"normal","cursor":{"row":0,"col":2},"anchor":{"row":0,"col":0}}
+{"name":"sel-regex-then-motion","text":"foo bar foo baz\n","mode":"normal","cursor":{"row":0,"col":3},"anchor":{"row":0,"col":2},"sels":[{"cursor":{"row":0,"col":3},"anchor":{"row":0,"col":2}},{"cursor":{"row":0,"col":11},"anchor":{"row":0,"col":10}}],"primary":0}
+{"name":"sel-regex-then-delete","text":"abc\n","mode":"normal","cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}},{"cursor":{"row":0,"col":3},"anchor":{"row":0,"col":3}}],"primary":0}
+{"name":"sel-regex-dot-newline","text":"ab\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}}],"primary":0}
+{"name":"sel-regex-caret","text":"ab\nab\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":1,"col":0}}],"primary":0}
+{"name":"split-regex-comma","text":"a,b,c\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}},{"cursor":{"row":0,"col":5},"anchor":{"row":0,"col":4}}],"primary":0}
+{"name":"split-regex-comma-tty","text":"a,b,c\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}},{"cursor":{"row":0,"col":5},"anchor":{"row":0,"col":4}}],"primary":0}
+{"name":"split-regex-lead","text":",a,b\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":1}},{"cursor":{"row":0,"col":4},"anchor":{"row":0,"col":3}}],"primary":0}
+{"name":"split-regex-trail","text":"a,b,\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}},{"cursor":{"row":0,"col":4},"anchor":{"row":0,"col":4}}],"primary":0}
+{"name":"split-regex-adjacent","text":"a,,b\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}},{"cursor":{"row":0,"col":4},"anchor":{"row":0,"col":3}}],"primary":0}
+{"name":"split-regex-ws","text":"one two three\n","mode":"normal","cursor":{"row":0,"col":2},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":0}},{"cursor":{"row":0,"col":6},"anchor":{"row":0,"col":4}},{"cursor":{"row":0,"col":13},"anchor":{"row":0,"col":9}}],"primary":0}
+{"name":"split-regex-ws-tty","text":"one two three\n","mode":"normal","cursor":{"row":0,"col":2},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":0}},{"cursor":{"row":0,"col":6},"anchor":{"row":0,"col":4}},{"cursor":{"row":0,"col":13},"anchor":{"row":0,"col":9}}],"primary":0}
+{"name":"split-regex-nomatch","text":"abc\n","mode":"normal","cursor":{"row":0,"col":3},"anchor":{"row":0,"col":0}}
+{"name":"split-regex-newline","text":"one\ntwo\nthree\n","mode":"normal","cursor":{"row":0,"col":2},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":2},"anchor":{"row":1,"col":0}},{"cursor":{"row":2,"col":4},"anchor":{"row":2,"col":0}}],"primary":0}
+{"name":"split-regex-esc","text":"a,b,c\n","mode":"normal","cursor":{"row":0,"col":5},"anchor":{"row":0,"col":0}}
+{"name":"split-regex-within-sels","text":"aXa\nbXb\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}},{"cursor":{"row":1,"col":0},"anchor":{"row":0,"col":2}},{"cursor":{"row":1,"col":3},"anchor":{"row":1,"col":2}}],"primary":0}
+{"name":"split-regex-end","text":"abc\n","mode":"normal","cursor":{"row":0,"col":1},"anchor":{"row":0,"col":0},"sels":[{"cursor":{"row":0,"col":1},"anchor":{"row":0,"col":0}},{"cursor":{"row":0,"col":3},"anchor":{"row":0,"col":3}}],"primary":0}
+{"name":"comment-line","text":"# alpha\nbeta\n","mode":"normal","cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}}
+{"name":"comment-toggle-back","text":"alpha\nbeta\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}}
+{"name":"comment-selection","text":"# alpha\n# beta\ngamma\n","mode":"normal","cursor":{"row":1,"col":6},"anchor":{"row":0,"col":2}}
+{"name":"comment-indent","text":" # alpha\n # beta\n","mode":"normal","cursor":{"row":1,"col":10},"anchor":{"row":0,"col":0}}
+{"name":"comment-indent-round-trip","text":" alpha\n beta\n","mode":"normal","cursor":{"row":1,"col":8},"anchor":{"row":0,"col":0}}
+{"name":"comment-blank-skipped","text":"# alpha\n\n# beta\n","mode":"normal","cursor":{"row":2,"col":6},"anchor":{"row":0,"col":2}}
+{"name":"comment-partial","text":"# # alpha\n# beta\n# gamma\n","mode":"normal","cursor":{"row":2,"col":7},"anchor":{"row":0,"col":2}}
+{"name":"comment-uncomment","text":"alpha\nbeta\n","mode":"normal","cursor":{"row":1,"col":4},"anchor":{"row":0,"col":0}}
+{"name":"comment-margin0","text":"alpha\n beta\n","mode":"normal","cursor":{"row":1,"col":5},"anchor":{"row":0,"col":0}}
+{"name":"comment-token-only","text":"\n\n","mode":"normal","cursor":{"row":1,"col":0},"anchor":{"row":0,"col":0}}
+{"name":"comment-uncomment-deep","text":"alpha\n # beta\n","mode":"normal","cursor":{"row":1,"col":8},"anchor":{"row":0,"col":0}}
+{"name":"comment-tab-indent","text":"\t# alpha\n\t# beta\n","mode":"normal","cursor":{"row":1,"col":7},"anchor":{"row":0,"col":0}}
+{"name":"comment-other-token","text":"# // alpha\n# // beta\n","mode":"normal","cursor":{"row":1,"col":9},"anchor":{"row":0,"col":2}}
+{"name":"comment-noeol","text":"# alpha","mode":"normal","cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}}
+{"name":"comment-empty","text":"\n","mode":"normal","cursor":{"row":0,"col":0},"anchor":{"row":0,"col":0}}
+{"name":"comment-only-blank","text":" \n\t\n","mode":"normal","cursor":{"row":1,"col":1},"anchor":{"row":0,"col":0}}
+{"name":"comment-select-mode","text":"# alpha\n# beta\n","mode":"normal","cursor":{"row":1,"col":2},"anchor":{"row":0,"col":2}}
+{"name":"comment-count-ignored","text":"# alpha\nbeta\ngamma\n","mode":"normal","cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}}
+{"name":"comment-undo","text":"alpha\nbeta\n","mode":"normal","cursor":{"row":1,"col":4},"anchor":{"row":0,"col":0}}
+{"name":"comment-multi-cursor","text":"# alpha\n# beta\ngamma\n","mode":"normal","cursor":{"row":1,"col":2},"anchor":{"row":1,"col":2},"sels":[{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}},{"cursor":{"row":1,"col":2},"anchor":{"row":1,"col":2}}],"primary":1}
+{"name":"comment-same-line-cursors","text":"# alpha beta\n","mode":"normal","cursor":{"row":0,"col":7},"anchor":{"row":0,"col":2}}
+{"name":"comment-cursor-gap","text":"# a\n# b\n# c\nd\n","mode":"normal","cursor":{"row":2,"col":2},"anchor":{"row":2,"col":2},"sels":[{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}},{"cursor":{"row":1,"col":2},"anchor":{"row":1,"col":2}},{"cursor":{"row":2,"col":2},"anchor":{"row":2,"col":2}}],"primary":2}
+{"name":"comment-split-cursors","text":"# alpha\n# beta\n# gamma\n","mode":"normal","cursor":{"row":0,"col":6},"anchor":{"row":0,"col":2},"sels":[{"cursor":{"row":0,"col":6},"anchor":{"row":0,"col":2}},{"cursor":{"row":1,"col":5},"anchor":{"row":1,"col":2}},{"cursor":{"row":2,"col":6},"anchor":{"row":2,"col":2}}],"primary":0}
+{"name":"comment-last-line","text":"alpha\nbeta\n","mode":"normal","cursor":{"row":2,"col":0},"anchor":{"row":2,"col":0}}
+{"name":"comment-then-insert","text":"# zalpha\n","mode":"normal","cursor":{"row":0,"col":3},"anchor":{"row":0,"col":3}}
+{"name":"comment-after-sel-regex","text":"# alpha\n# beta\n# gamma\n","mode":"normal","cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2},"sels":[{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}},{"cursor":{"row":0,"col":6},"anchor":{"row":0,"col":6}},{"cursor":{"row":1,"col":5},"anchor":{"row":1,"col":5}},{"cursor":{"row":2,"col":3},"anchor":{"row":2,"col":3}},{"cursor":{"row":2,"col":6},"anchor":{"row":2,"col":6}}],"primary":0}
+{"name":"comment-after-split-regex","text":"# a,b\n# c,d\n","mode":"normal","cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2},"sels":[{"cursor":{"row":0,"col":2},"anchor":{"row":0,"col":2}},{"cursor":{"row":1,"col":2},"anchor":{"row":0,"col":4}},{"cursor":{"row":1,"col":5},"anchor":{"row":1,"col":4}}],"primary":0}
diff --git a/test/hxcases/parity-waivers.jsonl b/test/hxcases/parity-waivers.jsonl
index d48f4670..1a6fd269 100644
--- a/test/hxcases/parity-waivers.jsonl
+++ b/test/hxcases/parity-waivers.jsonl
@@ -8,3 +8,6 @@
{"name":"zj-noop-in-band","reason":"viewport geometry: same as zj-snaps-cursor - the terminal's view cannot scroll past the live grid bottom, so the cursor's band differs by one row."}
{"name":"zk-bottom-snap","reason":"viewport geometry: zk scrolls the view up one row and snaps the cursor; the terminal's starting view offset differs because it could not scroll as far down in the first place."}
{"name":"unindent-tab","reason":"the case text is not representable in a pty pane: a literal TAB fed through the terminal is expanded to the next tab stop by the emulator, so the shell rows hold spaces and never the tab the file pane unindents. Not an editing divergence - unindent-basic, unindent-partial, unindent-realign and unindent-cursor all match; only a byte a terminal cannot hold verbatim."}
+{"name": "comment-tab-indent", "reason": "the case text is not representable in a pty pane: a literal TAB fed through the terminal is expanded to the next tab stop by the emulator, so the shell rows hold spaces and the comment token goes in at a different column. Exactly the unindent-tab waiver's class - not an editing divergence; comment-indent, comment-uncomment-deep and the rest of the comment-* family match."}
+{"name": "comment-noeol", "reason": "the case text is not representable in a pty pane: it is the one case in the corpus with NO trailing newline (that is the point - it pins helix's last-line handling), and the tty harness re-adds the newline ghostty's dump trims off the cursor row. The comment itself is identical on both sides; only the missing final byte differs."}
+{"name": "comment-only-blank", "reason": "the case text is not representable in a pty pane: a literal TAB (unindent-tab's class) plus an all-whitespace last row, which the terminal dump trims off entirely. Both panes correctly change nothing - toggle_comments skips blank lines - so the only difference is what the pty could hold in the first place."}
diff --git a/test/hxcases/waivers.jsonl b/test/hxcases/waivers.jsonl
index 8110a84c..6b2f612c 100644
--- a/test/hxcases/waivers.jsonl
+++ b/test/hxcases/waivers.jsonl
@@ -1,2 +1,6 @@
{"name":"wiX-edit-drops-sel","reason":"helix maps the selection through every insert-mode edit; pardes drops it on the first edit instead (anchor-only divergence, text+cursor+mode match). Re-judged phase 5 and kept: mapping the anchor through all ~23 mutation sites in handleInsert (multi-line inserts, EOL joins, kill runs) is genuinely invasive, and nothing in pardes consumes an implicit selection after insert-mode typing - the acme chords need explicit selections, which never enter insert."}
{"name":"alt-c-window-op","reason":"deliberate pardes binding: Alt-c is the move-pane-to-fresh-column window op in ANY mode (do-not-touch contract); helix Alt-c is change-noyank. Alt-d + i covers the helix behavior; the buffer is untouched on the pardes side."}
+{"name":"msel-append","reason":"multiple cursors + `a`: pardes restores the appended-over span for the PRIMARY only, because Pane.append_at (where the append session began) is a single field and the other ranges have nowhere to keep their own origin. Every cursor lands on the right cell and the text matches; only the secondaries' anchors differ, so they read as bare cursors instead of spanning what was typed. Same family as wiX-edit-drops-sel: pardes does not map selections through insert-mode edits. Fix = an origin per SelRange."}
+{"name":"msel-yank-paste","reason":"pardes has ONE yank register; helix's holds one VALUE PER RANGE and pastes value[i] back at range[i]. A multi-range `y` in pardes therefore joins the ranges' text with newlines and `p` puts the whole newline-joined blob at every cursor (which also makes it linewise). Deliberate: a per-range register is its own feature, not part of the selection model. Single-range yank/paste is unaffected and covered by the yank-* / paste-* cases."}
+{"name": "sel-regex-dot-newline", "reason": "mvzr's `.` matches ANY byte, newlines included; helix builds its pattern with the Rust regex crate, where `.` excludes \\n unless asked. So `%s.` selects one range per byte in pardes and one per non-newline byte in helix. Deliberate: closing it means rewriting `.` to `[^\\n]` inside the pattern, and doing that correctly needs a real parse (`\\.` is a literal dot, a `.` inside `[...]` is already literal) - a regex parser written to work around the regex engine. `[^\\n]` typed at the prompt is the workaround, and it behaves identically in both editors."}
+{"name": "sel-regex-caret", "reason": "helix compiles the `s`/`S` pattern with multi_line(true), so `^` and `$` are LINE anchors; mvzr has no such flag and asserts them against the START OF THE SLICE it is handed, which pardes advances to each match's end. `%s^a` therefore finds one match in pardes and one per line in helix. Same root cause for `$`. Fixing it means either searching line by line - which changes which ranges come out for every OTHER pattern, since a match may not span a line then - or an engine with multi-line assertions. Every other anchor-free pattern agrees, including \\b (sel-regex-boundary)."}