Editing

Insert mode entry

KeysWhere the cursor lands
iBefore current char
aAfter current char
IBeginning of current line
AEnd of current line
oNew line below, cursor on it (continues a comment leader — see below)
ONew line above, cursor on it (continues a comment leader — see below)

Each entry opens an undo transaction that closes on <Esc>. The whole session — every typed character, every backspace — becomes ONE undo entry (matches vim).

In insert mode:

Comment continuation

When you open a line inside a comment — with o, O, or <Enter> — the comment leader is carried onto the new line, so you don't retype it:

/**                 press o here
 * Multiline          → new line starts with " * "
 */

Recognised in C-family filetypes (c, cpp, java, javascript, typescript, go, rust):

The leader is only recognised at the start of the line, so a trailing comment (x = 1; // note) does not trigger continuation. This is built in (no comments/formatoptions config, no runtime files) and is gated on options.smartindent, like the other smart-indent rules.

Open-paren alignment

In C-family filetypes and Rust, pressing <Enter> on a line with an unclosed ( aligns the continuation just past that paren — under the first argument — like vim's default cindent:

int something(int val1,      press <Enter> here
              int val2)       → continuation aligns under "int val1"

Alignment kicks in only when there is content after the open paren (a bare trailing foo( still gets a normal one-level indent), it targets the innermost unclosed paren, and it ignores parens inside string/char literals or after a // comment. Gated on options.smartindent.

Delete operators

All count-aware. Pre-operator count × post-operator count multiplies.

KeysAction
ddDelete current line (linewise)
djDelete current line + line below (= 2 lines; 4dj = 5 lines)
dkDelete current line + line above
dwDelete to start of next word
dbDelete back to previous word start
deDelete through end of current word (inclusive)
d$ / DDelete to end of line
d0Delete to start of line
dGDelete to end of buffer (or to line N if count given)
dggDelete to start of buffer (or to line N)
xDelete char under cursor (3x = 3 chars, capped at EOL)
XDelete char before cursor

Indent / dedent

KeysAction
>>Indent current line by one shiftwidth (3>> = three lines)
<<Dedent current line by one shiftwidth
> (in visual)Indent every line touched by the selection
< (in visual)Dedent every line touched by the selection

The indent unit follows options.expandtab:

Dedent removes up to one shiftwidth's worth of leading whitespace, counting display columns: a leading tab counts as tab_width columns immediately, so a single << removes either one tab or up to tab_width spaces (whichever is at the start). Lines with less than a full shiftwidth of indent lose what they have.

All affected lines collapse into a single undo entry.

Deleted text goes into the unnamed register by default, so p pastes it back. Prefix with "<letter> to target a named register ("ayy, "ap) or the system clipboard ("qyy / "qp — see registers.md).

Yank operators

Identical ranges to the delete operators, but the buffer is not modified and the cursor stays put.

KeysAction
yy / YYank current line (linewise)
yjYank current + line below
ykYank current + line above
ywYank to start of next word
ybYank back to previous word start
yeYank through end of current word (inclusive)
y$Yank to end of line
y0Yank to start of line
yGYank to end of buffer
yggYank to start of buffer

Paste

KeysAction
pPaste below current line (linewise) OR after cursor (charwise), depending on how the register was filled.
PPaste above current line (linewise) OR before cursor (charwise) — the same register, placed on the other side.

Both honour the "<letter> register prefix ("aP, "qp, …).

Change

KeysAction
c{motion}Delete the motion's range, then enter insert mode.
cc(= c$ for the line) — currently not bound separately; use dd + i.

In visual modes, c deletes the selection and drops into Insert. For visual-block, that's the start of a block-replace session.

Replace

KeysAction
r{c}Replace char under cursor with {c}. Cursor stays put.
5rXReplace 5 chars (capped at EOL).
r<Enter>Replace with a newline (splits the line).
r<Tab>Replace with a tab.
r<Esc>Cancel — no change.

In visual / visual-line modes: r{c} replaces every selected character with {c}, preserving newlines, in a single undo step.

In visual-block mode: r{c} replaces every cell of the rectangle with {c}, again as a single undo step.

Replace mode (R)

R enters Replace (overtype) mode — the statusline shows REPLACE. Typed characters overwrite the character under the cursor and advance; once the cursor passes the old end of line, further characters extend the line as in insert mode.

KeysAction
REnter Replace mode
(any char)Overwrite the char under the cursor, advance
<Backspace>Restore the overtyped character (or delete an appended one); rejoins on a broken line
<Enter>Break the line at the cursor
<Esc> / <C-c>Leave to Normal; cursor steps left one column

<Backspace> walks back through your changes, putting the original characters back; once you backspace past where you started it just moves left without destroying untouched text. The whole session is a single undo step. Replace mode is refused on read-only render buffers, like Insert.

Undo / redo

KeysAction
uUndo last transaction
<C-r>Redo

A transaction can include many edits — see visual-mode.md for block ops, which collapse the whole rectangle change (top-row typing + cross-row replay) into one entry.

Counts

Counts compose vim-style:

3yy        → yank 3 lines
4dj        → delete 5 lines (current + 4 below)
2d3w       → delete 6 words
5rX        → replace 5 chars with X
3p         → paste 3 times (count on `p` isn't implemented yet)

(p doesn't currently respect a count — single paste only.)

File save

Ex commandAction
:wWrite current buffer to disk
:w <path>Save as
:wqWrite then quit
:q!Quit discarding changes

See command-line.md for the full ex command surface.

Behaviour notes