Added
- Which-key for all partial keys — the which-key overlay now triggers on any partial key sequence (operators like
d,c,yand prefix keys likeg,z,[,]), not just the leader key. After a 500ms delay, a multi-column panel at the bottom of the editor shows available continuations. Configurable via Settings → Vim Motions → Which-key hints with three modes: off, leader key only, all partial keys (default: off).- Operator-pending mode (
d …) shows grouped next-key options: single-key motions directly (w,j,$), multi-key prefixes collapsed (i→ +N text objects,a→ +N text objects) - Partial prefix keys (
g …,z …) showgetCompletions()results from the fork's keymap introspection API - Special keys (
<Left>,<C-n>, etc.) and insert-only entries are filtered out - Leader bindings from settings and vimrc are shown with friendly command names
- Overlay positioned at bottom of editor pane (not viewport), max 40% height, multi-column grid layout
- Operator-pending mode (
- E2E test suite
test/specs/which-key.e2e.tswith 31 tests covering all three modes (off/leader/all), settings hot-reload, leader registry integration, and fork API integration (getKeymap/getCompletions)
Changed
- Which-key setting —
enableWhichKeyboolean replaced withwhichKeyModedropdown ('off'|'leader'|'all'). Default changed from implicit leader-only to explicit'off'. - Which-key overlay rewritten —
WhichKeyOverlayclass generalized from leader-only to support any partial key sequence. UsesgetInputState()for operator-pending detection andvim.statusfor partial key chord display. DOM attachment changed fromeditorEl.parentElementtoview.contentElfor reliable positioning. VimStatetype fix —modefield changed from required'normal' | 'insert' | 'visual' | 'replace'to optionalstringto match runtime behavior (the field is only set by the CM6 ViewPlugin's mode-change handler, not by the initial vim state).- Plugin deviations reduced —
test/neovim/deviations.tsreduced from 20 to 10 entries. 10 deviations removed after verifying the fork now matches Neovim:)sentence motion,di(multiline,dbcross-line,dwempty line,d2wcross-line,dgeempty lines,diwword boundary,da"trailing space,:joincursor,:globalcursor. - Fork test count — 17 new fork-level tests for async motion dispatch (6),
getKeymap()API (5), andgetCompletions()API (6). Total: 1628 fork tests passing. - Fork golden comparison — re-recorded 756 golden cases from Neovim 0.12.2 with per-step state capture. 476 pass, 0 unexpected diffs, 280 known deviations (down from 284). Fixed 3 duplicate test name collisions and empty
:sflag behavior.
Fixed
da"trailing space —da"onsay "hello world" endnow producessay end(single space) instead ofsay end(double space). The fork'sfindBeginningAndEndnow consumes adjacent whitespace after inclusive quote expansion, matching Neovim.:joincursor position —:joinex command now positions cursor at column 0 of the joined line, matching Neovim. Previously placed cursor at the join point.:globalcursor position —:g/pattern/dnow positions cursor at the last matched line after execution, matching Neovim. Non-destructive:gcommands leave cursor where the last sub-command placed it.- Empty
:sflag behavior —:swith no arguments no longer preserves the/gflag from the previous substitution. Only the first match on the line is replaced, matching Neovim. %string-awareness — updatedKNOWN_LIMITATIONS.mdto reflect that%is only partially fixed: the forward-seek check works, butfindMatchingBracketstill does positional counting without string awareness.- Which-key graceful degradation —
getInputState(),getKeymap(), andgetCompletions()calls in the which-key overlay now checktypeofbefore invocation, preventing errors when built-in vim mode is active (these APIs are fork-only). - Cursor shape settings in built-in mode — cursor shape dropdowns are now disabled with an explanatory message when Obsidian's built-in vim mode is active (cursor shapes require bundled fork mode).
- g-commands golden data — corrected incorrect Neovim recordings for
g$(cursor ch:11→10, mode visual→normal) andguu(content unchanged→lowercased). Full vim-builtin e2e suite now passes 16/16.
Documentation
DIFFERENCES.md(fork): added "Keymap introspection API" section documentinggetKeymap()andgetCompletions()DIFFERENCES.md(fork): updated "Empty :s flag preservation" → "Empty :s uses default flags", addedda"whitespace,:joincursor,:globalcursor sections, updated golden comparison statsKNOWN_LIMITATIONS.md: "Which-key overlay scope" section rewritten to reflect the new all-keys modeKNOWN_LIMITATIONS.md: updated%+ strings entry to "Partially fixed" with explanation of remainingfindMatchingBracketlimitationKNOWN_LIMITATIONS.md: addedda",:join,:global,:sempty entries to behavioral deviations tableKNOWN_LIMITATIONS.md: correctedvi*single-char status from "Fixed" to "Not fixed"AGENTS.md: updated fork test count (1421→1628) and golden comparison statsREADME.md: which-key description updated and settings list updated with new dropdown
Full Changelog: 0.13.0...0.14.0