Vim mode¶
On by default. vim_mode = false turns it off, and the editor then
behaves like any other — keys type, Ctrl+S saves, Ctrl+Z undoes.
This is not a full Vim. It is the subset that gets used, pinned by 218 conformance cases whose expected output was generated by running real vim, so where it differs from Vim that is a bug rather than a decision.
Modes¶
Normal, Insert, Visual, Visual Line, Replace. The current one
is in the bottom-left. Esc always goes back towards Normal.
A half-typed command shows in the status bar as you type it, so 2d
sitting there waiting for a motion is visible rather than a key that
seemingly did nothing.
What is implemented¶
Motions — h j k l w W b B e E 0 ^ $ G gg f F t T ; , % { }, arrows,
and counts on all of them.
Operators — d c y > <, each taking a motion or a count: d2w,
3dd, c$, >j. Doubling the operator takes the line: dd, cc,
yy, >>.
Text objects — iw aw iW aW, and i/a with ( ) b, { } B,
[ ], < >, ", ' and `. So ciw, da(, di{, yi".
Editing — x X r R s S J gJ ~ p P o O a A I i C D, and Ctrl+A /
Ctrl+X to increment and decrement the number under the cursor. ~
toggles the case of the character under the cursor (and of the selection
in Visual mode); it is not an operator, so there is no g~.
Registers — named "a to "z, uppercase to append. The unnamed
register behaves as Vim's does.
Marks — ma to set, `a to jump exactly, 'a to jump to the
line's first non-blank. Uppercase marks are global and name a file as
well as a position.
Macros — qa to record, q to stop, @a to play, @@ to repeat.
Counts work: 10@a.
Repeat — . repeats the last change, including after ciw, f, a
macro, or a mark.
Search — / and ?, n and N, * and # for the word under
the cursor.
Visual — v and V. Operators apply to the selection, and o swaps
which end you are moving. r, J, ~, > and < work on it too.
Beyond Vim — gd goes to the definition under the cursor, using the
language server rather than a local scan.
Indentation¶
A new line starts where the one it came from started — from o, O and
Enter. The leading whitespace is copied exactly, so a tab-indented file
stays tab-indented and nothing is silently converted.
An indent you never type on is taken back: o then Esc leaves the line
empty rather than full of spaces, as vim does.
auto_indent = false turns it off. It is on by default, which is a
deliberate divergence — vim ships autoindent off and nearly every vimrc
turns it on. See
ADR 0136.
Moving the keys¶
vim.normal.<key> = <keys> in your config is vim's nnoremap: the key
on the left stands for the keys on the right, before anything else looks
at it.
vim.normal.Y = y$ # the classic
vim.n = j # a layout remap, in Normal and Visual
vim.e = k
vim.visual.<key> is Visual only; plain vim.<key> is both, and a
mode-qualified one wins.
Because the substitution happens before the dispatcher, a count and a
pending operator compose with it — 3n and dn work as 3j and dj
without saying anything more.
The right-hand side is not itself remapped, so two keys can be
swapped without looping. And a key that is an argument — the target of
f, the register after ", the object after i — is never remapped,
or f could not find a character you had rebound.
A remap that names no single key is reported when you save the config, not ignored. See ADR 0134.
The command line¶
: opens it. See The command line for what it takes,
including :s/from/to/ and :42 to jump to a line.
What is not implemented¶
Blockwise visual (Ctrl+V), the case operators (gU, gu, g~),
windows and splits as Vim has them (this editor's regions use Ctrl+W
but are not Vim windows), folds, :g, registers beyond a–z and the
unnamed one, and Vim's own scripting.
Vim-mode work stopped deliberately at the point where what remained was long-tail rather than daily. If something you use every day is missing, that is worth reporting.