github saberzero1/motions 0.6.0

latest releases: 1.0.0, 0.150.0, 0.149.0...
3 months ago

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/daB on 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/gp to use direct register-reading implementation instead of delegating through Vim.handleKey, avoiding re-entrancy issues with the new P override.

Neovim test infrastructure

  • Ex commands (:s, :sort, :d, :yank, :join, :noh, :undo, :redo, :global) now work correctly in Neovim golden comparison tests — added dispatchVimKeys routing that detects Ex command sequences and dispatches them via Vim.handleEx() instead of character-by-character key input.

Changed

  • test/neovim/deviations.ts reduced 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.md behavioral deviations table expanded with 5 entries for confirmed upstream constraints (dG, >>, V+>, d0, <<) that cannot be intercepted via mapCommand due 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 official neovim npm package. Spawns nvim --embed --headless, provides setContent(), 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 with loadGoldenFile(), 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.tstestWithNeovim() 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/ge across empty lines, at document boundaries, with punctuation, count clipping, line wrapping.
  • Operator edge cases: dw at end of line, dd on last/only line, d2w/2dd, D, dk, dj on last line, de/db, dG/dgg, dfx/dtx, cw vs ce, cc/C/2cc.
  • Text object edge cases: iw/aw on whitespace, iW/aW with mixed punctuation, nested i(/i{/i[, di( across lines, d2aw with count, i" with escaped quotes.
  • Character search edge cases: f/t not crossing line boundaries, 2t/2F counts, ; after t, , reversal.
  • Visual mode edge cases: viw, v3l+d, gv reselect, V+y linewise, visual at document boundaries.
  • Yank/register edge cases: yy/yw linewise flag, y$ without newline, numbered register rotation, "Ayy append, ". last inserted text.
  • Repeat edge cases: . after dw/>>/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 the yaml package, fixing npm run test:coverage which previously reported 0/0 on the multi-line manifest format.

Changed

  • Replaced js-yaml dependency with yaml — better maintained, YAML 1.2 spec-compliant, ships its own types.
  • All 16 Tier 1 test files (test/specs/vim-builtin/*.e2e.ts) now use testWithNeovim() as the primary test format alongside existing it() blocks. Neovim lifecycle hooks (startNvim/stopNvim) added to top-level before/after.
  • test/helpers.ts — added vimRawKeys() for raw byte key sequences (supports \x1b for Escape, \x01-\x1a for Ctrl keys, \n for 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 (dG trailing newline, iB nesting, di* on delimiter, dot-repeat of cw, ) cursor off-by-one, n/N wrap-around).

Full Changelog: 0.5.1...0.6.0

Don't miss a new motions release

NewReleases is sending notifications on new releases.