Fixed
Neovim deviation closure
di*/da*with cursor on delimiter now correctly no-ops — previously the delimiter scanner treated the delimiter position as "inside", operating on the text. Matches Neovim behavior.diB/daBon nested blockquotes (>>) now correctly scopes to the innermost nesting level — previously deleted all blockquote content regardless of depth.P(paste before cursor) now places cursor on the last pasted character, matching Neovim — previously CM Vim placed cursor one position further.- Rewrote
gP/gpto use direct register-reading implementation instead of delegating throughVim.handleKey, avoiding re-entrancy issues with the newPoverride.
Neovim test infrastructure
- Ex commands (
:s,:sort,:d,:yank,:join,:noh,:undo,:redo,:global) now work correctly in Neovim golden comparison tests — addeddispatchVimKeysrouting that detects Ex command sequences and dispatches them viaVim.handleEx()instead of character-by-character key input.
Changed
test/neovim/deviations.tsreduced from 28 to 19 entries (9 removed, 3 new cursor-position deviations added for Ex commands where content is correct but cursor placement differs from Neovim).KNOWN_LIMITATIONS.mdbehavioral deviations table expanded with 5 entries for confirmed upstream constraints (dG,>>,V+>,d0,<<) that cannot be intercepted viamapCommanddue to codemirror-vim's operator-pending dispatch architecture.
Added
Neovim golden comparison testing
- Neovim-backed golden comparison system for Tier 1 Vim behavior tests, inspired by Zed editor's
NeovimBackedTestContext. Sends identical keystrokes to both Obsidian and a headless Neovim instance, compares resulting editor state (content, cursor, mode). test/neovim/client.ts— Neovim RPC client wrapping the officialneovimnpm package. Spawnsnvim --embed --headless, providessetContent(),setCursor(),input(),getContent(),getCursor(),getMode(),getRegister().test/neovim/compare.ts— state comparison helpers:getObsidianState(),getNeovimState(),compareStates().test/neovim/golden.ts— golden file read/write infrastructure withloadGoldenFile(),saveGoldenFile(),findGoldenCase().test/neovim/deviations.ts— known deviation registry tracking behavioral differences from Neovim.isKnownDeviation()silently allows expected behavioral differences during golden comparison.test/neovim/test-wrapper.ts—testWithNeovim()function: the primary test format for Tier 1 tests. Operates in playback mode (golden files, no Neovim needed) or compare mode (NEOVIM_COMPARE=1, live Neovim).test/neovim/test-definitions.ts— 199 test case definitions across 16 suites covering motions, operators, text objects, editing, yank/put, insert entry, visual mode, g-commands, bracket commands, insert mode, scroll (Ctrl-A/X), and Ex commands.test/neovim/record-golden.ts— standalone script to record golden files from Neovim without running Obsidian. Usage:npm run test:neovim-record.test/neovim/smoke.ts— Neovim client smoke test. Usage:npm run test:neovim-smoke.- 16 golden files in
test/neovim/golden-data/recorded against Neovim 0.12.2. - npm scripts:
test:neovim-smoke,test:neovim-record,test:neovim-compare.
Edge-case test expansion
- 110 new edge-case tests translated from Neovim's legacy test suite (
test/old/testdir/), replit/codemirror-vim (test/vim_test.js), and VSCodeVim (test/motion.test.ts). - Word motion edge cases:
w/b/e/geacross empty lines, at document boundaries, with punctuation, count clipping, line wrapping. - Operator edge cases:
dwat end of line,ddon last/only line,d2w/2dd,D,dk,djon last line,de/db,dG/dgg,dfx/dtx,cwvsce,cc/C/2cc. - Text object edge cases:
iw/awon whitespace,iW/aWwith mixed punctuation, nestedi(/i{/i[,di(across lines,d2awwith count,i"with escaped quotes. - Character search edge cases:
f/tnot crossing line boundaries,2t/2Fcounts,;aftert,,reversal. - Visual mode edge cases:
viw,v3l+d,gvreselect,V+ylinewise, visual at document boundaries. - Yank/register edge cases:
yy/ywlinewise flag,y$without newline, numbered register rotation,"Ayyappend,".last inserted text. - Repeat edge cases:
.afterdw/>>/cw+text,3.with count. - Search edge cases:
*/#wrap-around. - Mark edge cases: mark persistence after edit,
'.jump to last change.
Fixed
test/coverage-report.ts— replaced broken regex YAML parser with proper YAML parsing via theyamlpackage, fixingnpm run test:coveragewhich previously reported 0/0 on the multi-line manifest format.
Changed
- Replaced
js-yamldependency withyaml— better maintained, YAML 1.2 spec-compliant, ships its own types. - All 16 Tier 1 test files (
test/specs/vim-builtin/*.e2e.ts) now usetestWithNeovim()as the primary test format alongside existingit()blocks. Neovim lifecycle hooks (startNvim/stopNvim) added to top-levelbefore/after. test/helpers.ts— addedvimRawKeys()for raw byte key sequences (supports\x1bfor Escape,\x01-\x1afor Ctrl keys,\nfor Enter).
Documentation
- README: added "Testing strategy" section describing the Neovim golden comparison system, test types (
[nvim]/[obsidian]/Tier 2), and available test commands. KNOWN_LIMITATIONS.md: added "Test-discovered behavioral discrepancies" section documenting 6 bugs found during edge-case test translation (dGtrailing newline,iBnesting,di*on delimiter, dot-repeat ofcw,)cursor off-by-one,n/Nwrap-around).
Full Changelog: 0.5.1...0.6.0