ADR 0106: WORDs, case, indent and numbers¶
Status¶
Accepted
Context¶
Four everyday vim commands were missing: W/B/E, ~, >>/<<, and
Ctrl+A/Ctrl+X. None is large, and all four are verifiable against real
vim the same way everything else in gui/tests/ is.
The suite found two bugs in the first one before it found any in the other three.
Decision¶
W B E fold punctuation into the word¶
w stops at a class boundary, so foo.bar is three words to it. W
splits on blanks only. Rather than a second family of scanners, the
existing ones take a big flag and vimClassifyAt reports Punct as
Word when it is set.
Two defects came out of wiring it:
vimWordBackward's inner scan calledvimClassifyAt(prev)without the flag, soBwalked back likeb. The outer scan had it; one call did not, and the result was a motion that looked implemented and was not.cw's change-to-word-end rule was keyed onm == 'w'alone, socWran asdWplus insert and swallowed the space after the WORD.
Both are the same shape: a parameter threaded through most of a path.
~ toggles ASCII case, count characters, never past the line end¶
A byte outside ASCII is left alone rather than guessed at. The cursor
lands one past the last byte changed, clamped back on to the line — ~
on the final character stays there.
>> and << are four spaces¶
Not shiftwidth: the render path has no tab-stop expansion (ADR 0031), a
literal tab measures about nothing wide, and Tab in Insert mode already
inserts four spaces. A second, configurable indent unit would be a second
answer to the same question.
They are operators, so >j, 2>> and Visual > all work. > is
linewise whatever motion delimited it, and an empty line stays empty.
The lines are edited bottom-up inside one undo session, because each edit
shifts the offsets of the lines below it.
Ctrl+A and Ctrl+X take the first number at or after the cursor¶
A run of digits, with a - immediately before it read as a sign. A .
is not part of a number, so 1.9 increments to 2.9 — vim's behaviour,
not an approximation of it. They are the only two Normal-mode commands
that are chords, so they are let through the modifier rejection at the
top of the key handler by name rather than by dropping the rejection.
That shadows Ctrl+A (select all) and Ctrl+X (cut) in Normal mode.
ADR 0046 set out to keep the Ctrl chain mode-independent and ADR 0059
already broke it for Ctrl+D/Ctrl+U on the same grounds: to anyone
with vim in their fingers these are increment and decrement, and Normal
mode is where they would reach for them. Insert mode, Visual mode and
vim_mode = false keep the editor's meanings, so the shadowing is
confined to the one mode that wants it.
Consequences¶
Thirty-eight cases were added to gui/tests/vim_cases.inc, derived from
vim as always. Where a command's result does not reveal where the cursor
landed, the case chains an x after it — ~x, >>x, <C-a>x — so the
landing is compared too, since the expectations are file contents.
The derivation script now sets shiftwidth=4 expandtab so vim's indent
matches the editor's unit. No other case is affected by it.
<< on an unindented line, >> on an empty one and >><< round-trip
all expect unchanged text. They are weak on their own, and they are the
cases that catch an over-eager << eating a non-space or >> indenting
a blank.
133 key cases and 19 command cases pass, and the ten suites are green.