Vim composer editing #
Scope #
Albedo implements a Vim-style composer subset, not an embedded Vim or Neovim. It covers Normal/Insert modes, basic motions, delete/change/yank operators, selected text objects, character finds, replacement, paste and undo/redo. Visual mode, dot-repeat, macros, buffer search and Ex commands are absent. There is no meaningful percentage of "full Vim" implemented; the tables below list the supported surface rather than implying full compatibility.
Both suite packages include the same Vim support.
Modes and application keys #
New chat models start in NORMAL; press i to type. The footer puts the mode
first, followed by ordinary application shortcuts and i type in NORMAL or
esc normal in INSERT. The mode
label is bold: NORMAL uses the
theme's cyan and INSERT its green (Base16 base0C/base0B when configured).
This edits only the unsent composer, never the transcript or already-submitted
messages.
| Key | Behavior |
|---|---|
Esc in Insert mode |
Enter Normal mode, including while an agent runs. An open command menu or transcript selection is dismissed first. |
Esc in Normal mode |
Cancel an unfinished count, operator or literal argument first. Otherwise interrupt a running/queued turn and restore cancelled queued input to the composer. |
i / a |
Insert at / after the cursor, including while an agent runs. |
I / A |
Insert at the first nonblank / end of the logical line. |
o / O |
Open one line below / above and enter Insert mode. |
/ in Normal mode |
Insert / at the cursor and enter Insert mode for slash commands. |
Enter |
Submit using the existing composer rules, in either mode. |
Shift+Enter |
Insert a newline, in either mode. |
Arrows, transcript paging, menus and external-editor integration retain their
application behavior. Ctrl+s opens sessions, Ctrl+o opens agents, and
Ctrl+j toggles diffs in either input mode; other control/Alt shortcuts remain.
Ctrl+r in Normal mode performs Vim-style redo. Unsupported unmodified
Normal-mode keys
are generally consumed without inserting text; they do not invoke Vim features.
When interruption cancels queued messages, their text, images and collapsed pastes return to an editable Insert-mode composer. Existing draft text stays first; multiple cancelled messages follow in queue order, separated by newlines. Inputs already delivered to the agent and newer uncancelled inputs are not restored.
Navigation outside the composer #
NORMAL/INSERT modes apply only to the chat input. Lists and search fields accept text immediately; use arrows and the existing control-key shortcuts to navigate. Agents, forms and transcript scrolling retain upstream behavior. There is no Space leader, workspace launcher, global keyboard reference or transcript mode.
Motions #
All the motions below work alone and with d, c or y, except where noted.
| Keys | Behavior |
|---|---|
h / l |
Move left / right within the logical line. |
j / k |
Move down / up by logical lines, not wrapped display rows. Operators use linewise ranges. |
w / b / e |
Next word start / previous word start / word end. |
0 / ^ / $ |
Line start / first nonblank / line end. |
gg / G |
First / last line; an explicit count selects a 1-based line number. Operators use linewise ranges. |
f{char} / F{char} |
Find the counted occurrence forward / backward on the current line. |
t{char} / T{char} |
Move just before / after a forward / backward character match. |
; / , |
Repeat the last successful character find in its original / opposite direction. |
Words distinguish whitespace, letters/digits/underscore and punctuation.
Uppercase W, B and E motions are not implemented, although iW/aW
text objects are. Character finds do not cross newlines or wrap around.
Editing, registers and history #
| Keys | Behavior |
|---|---|
d{motion} / c{motion} / y{motion} |
Delete / change / yank the motion's range. Change enters Insert mode. |
dd / cc / yy |
Delete / change / yank logical lines. |
D / C |
Delete / change from the cursor through the counted line end. |
x / X |
Delete characters at / before the cursor, within the line. |
r{char} |
Replace the counted characters without entering Insert mode; no change if too few remain on the line. |
p / P |
Paste after / before the cursor; linewise registers paste below / above. |
u / Ctrl+r |
Undo / redo composer changes, with counts. |
There is one composer-local register, populated by yank and deletion. It is not Vim's named/numbered register system. Yanks also use the application clipboard transport; application clipboard shortcuts remain available.
Undo stores up to 100 snapshots. An insertion or change and its following typed text undo together after returning to Normal mode. Paste, external-editor results and attachment edits also participate in composer history. Submission clears undo, redo, pending input and the local register; none of these commands undo submission. Deletion overlapping an attachment marker removes the entire marker to keep its payload atomic.
Text objects #
Use d, c or y, followed by i (inner) or a (around), then an object key.
For example: diw, ci", ya( and d2iW.
| Object keys | Inner / around range |
|---|---|
w |
Word / word with adjacent whitespace. |
W |
Whitespace-delimited WORD / WORD with adjacent whitespace. |
(, ), b |
Inside / including parentheses. |
[, ] |
Inside / including square brackets. |
{, }, B |
Inside / including braces. |
<, > |
Inside / including angle brackets; not HTML/XML tag parsing. |
| Single quote, double quote, backtick | Inside / including a quoted pair on the current logical line. |
Word objects accept counts. Paired delimiters support nesting: a count selects
an enclosing outer pair, such as d2a(. Quote objects accept only a single pair;
counts greater than one do nothing. Delimiter matching is textual, not
language-aware, and does not provide all Vim text-object edge-case semantics.
Counts and compatibility limits #
- Counts work for motions,
d/c/yoperators, character deletion/replacement, register paste and undo/redo. Examples:3w,2dd,d2w,2d3w,3fx,2p. Operator and motion counts multiply; counts are capped at 999. 2Gand2ggselect line 2.2$selects the next line's end.0without a preceding count is the line-start motion.- Counts do not repeat inserted text or opened lines:
3iis not Vim's repeated insertion, and3ostill opens only one line. - Cursor/range calculations use Unicode code points, not full grapheme-cluster semantics. Do not assume identical Vim behavior for combining characters.
- Normal-mode startup does not force a return to Normal after every submission; the current mode is retained.
Not implemented #
| Area | Examples of missing Vim features |
|---|---|
| Modes | Characterwise, linewise and blockwise Visual mode (v, V, Ctrl+v); Replace mode (R). |
| Repetition and automation | Dot-repeat (.), macro recording/playback (q, @), mappings and vimrc configuration. |
| Search | Buffer search (/, ?, n, N, *, #), regular expressions and substitution. / enters INSERT with a slash; slash commands remain available in INSERT. |
| Other motions | W/B/E, %, ge/gE, paragraph/sentence motions, marks, jumps and Vim window/screen motions. |
| Other edits | s/S, Y, J/gJ, indentation (>/<), case operators (~/gu/gU), formatting and numeric increment/decrement. |
| Other text objects | Sentences, paragraphs, tags, Visual-mode objects and plugin-defined objects. |
| Registers | Named/numbered registers, black-hole register, register selection ("a), clipboard registers and register insertion. |
| Ex/editor features | : commands, file/buffer/window/tab management, folds, plugins and persistent Vim undo history. |
Implementation and verification #
- Mode and prefix adapter.
- Pure motions and operator ranges.
- Literal arguments and text objects.
- Editor actions.
The TestVim* regressions cover parser counts/cancellation, motions and operators,
literal arguments, text objects, undo/redo, attachment/input lifecycle and footer
rendering. Both client package check phases run
go test ./internal/tui -run '^TestVim' -count=1 -v against the overlaid pinned
upstream source. Tests establish the supported subset, not complete Vim parity.