github saberzero1/motions 0.10.0

latest releases: 1.4.0, 1.3.1, 1.3.0...
3 months ago

Added

  • Bundled codemirror-vim fork — when Obsidian's built-in vim mode is disabled, the plugin provides a forked @replit/codemirror-vim as a CM6 extension with Neovim-parity behavioral fixes. A window.CodeMirrorAdapter.Vim bridge ensures ecosystem plugins (obsidian-vimrc-support, vim-im-control, etc.) work transparently.
  • Async motion support — the fork's defineMotion now accepts async functions returning Promise<Pos>, enabling EasyMotion to work natively as a motion instead of an action. Operator-pending (d/c/y + easymotion) and visual mode (v + easymotion) work through the standard vim dispatch.
  • Neovim golden comparison infrastructure in fork — 496/688 tests passing against headless Neovim, with per-step extraction, golden recording, and automated comparison (npx tsx test/neovim/compare.ts).
  • E2E tests for operator-pending easymotion (d/c/y + easymotion w)
  • E2E tests for multiline bracket text objects (di{/di[/di< across lines, same-line verification)
  • E2E tests for % string-awareness, db/d2w cross-line whitespace, dd cursor column preservation, J trailing whitespace
  • Expected-failure test cases for 6 remaining fixable deviations (dw cursor, d2w scope, dge empty, db cross-line, % quoted brackets, N after search)
  • Full vim-easymotion default motion set — all 17 default-mapped motions: find (f, F, s, t, T), word (w, b, e, ge, W, B, E, gE), line (j, k), search (n, N)
  • Bidirectional easymotion variants — easyMotionBdWord, easyMotionBdEndWord, easyMotionBdWORD, easyMotionBdEndWORD, easyMotionBdLine, easyMotionBdTill available as named actions for vimrc remapping
  • Repeat last easymotion motion — easyMotionRepeat action replays the most recent easymotion jump
  • 2-character combo labels — SCTree algorithm assigns single-char labels to nearby targets and 2-char labels to distant targets when there are more targets than label characters (>26). Backspace resets after typing the first char of a 2-char label.
  • Text dimming — non-target text is dimmed when easymotion is active, making labels more visible. Controlled by Settings → Vim Motions → EasyMotion dimming (on by default).
  • Visual mode support — all easymotion motions work in visual mode. v + easymotion extends the character selection to the target, V + easymotion extends the line selection. Uses CM6 dispatch({ selection }) to manipulate the selection range directly.
  • EasyMotion dimming setting — easyMotionDimming toggle in settings UI
  • Spike test test/specs/spikes/spike19-easymotion-visual.e2e.ts investigating CM Vim visual mode and operator-pending feasibility (6 questions answered)
  • E2E test file test/specs/easymotion-comprehensive.e2e.ts with 22 tests covering cursor landing (word, char, line, ge/gE), 2-char labels, dimming, repeat, visual mode, and edge cases (empty document, single word, empty lines, non-existent char)
  • E2E test file test/specs/easymotion-visual.e2e.ts with 4 tests covering visual mode overlay, charwise selection, linewise selection, and escape preservation
  • CSS classes: .vim-motions-easymotion-shade (dimming overlay), .vim-motions-easymotion-label-first and .vim-motions-easymotion-label-second (2-char label styling)

Fixed

  • dd cursor column preservation — cursor now stays at its original column after linewise delete (matching Neovim), instead of moving to first non-blank character
  • J trailing whitespace — join now strips trailing whitespace from the current line before adding the join space, preventing double spaces
  • di{/di[/di< multiline — inner bracket text objects on multiline brackets now preserve the bracket lines (producing a{\n}b instead of a{}b), matching Neovim
  • dj/dk at document boundary — dj on the last line and dk on the first line are now no-ops (matching Neovim), instead of deleting the content
  • :s cursor positioning — cursor after substitute now goes to first non-blank of the last affected line instead of column 0
  • % string-awareness — % now aborts (no movement) when the first bracket candidate found via forward-seeking is inside a string token, matching Neovim
  • db/d2w cross-line whitespace — when a delete crosses a line boundary, the whitespace-only prefix before the cursor is now included in the deletion, matching Neovim
  • dge at document start — ge at the start of the document is now a no-op instead of deleting the character under cursor
  • dge on empty lines — dge on double-empty-lines now deletes both lines (matching Neovim) instead of leaving one
  • ]p tab remainder — ]p with indentWithTabs now preserves remainder spaces when indent doesn't divide evenly by tabSize
  • EasyMotion visual mode — async motions now properly update visual selection head/anchor instead of just moving cursor
  • EasyMotion escape dismissal — Escape overlay dismissal in e2e tests now uses real DOM events (browser.keys) instead of Vim.handleKey which bypasses the DOM listener
  • Hint mode escape dismissal — same fix as EasyMotion
  • Workspace test isolation — workspace tests now use beforeEach with loadSingleFileWorkspace() to prevent cascading failures from gd navigation
  • Settings reload Y/Q test — uses Vim.handleKey instead of browser.keys to avoid DOM event routing issues after reloadFeatures()
  • Vim cursor styling — fork's hardcoded #ff9696 cursor color replaced with Obsidian CSS variables (--interactive-accent, --text-on-accent) directly in the fork's block-cursor.ts with fallbacks for non-Obsidian environments
  • Settings notice — when Obsidian's built-in Vim mode is enabled, the plugin settings tab shows a callout-style warning recommending to disable it, with an explanation of the fork's benefits
  • dw on empty line cursor — cursor after dw on an empty line before a whitespace-only line now positions at ch:1 instead of ch:0
  • Ambient type declarations — src/types/codemirror-vim.d.ts provides fallback types for vim(), getCM(), and Vim when the fork's build artifacts are unavailable (e.g. in the community scanner's sandboxed environment)

Changed

  • Recommended setup: disabling Obsidian's built-in vim mode is now the recommended configuration. The plugin's bundled fork provides Neovim-correct behavior, async motion support, and theme-aligned cursor styling that are not available with the built-in vim engine.
  • EasyMotion architecture — EasyMotion motions are now registered via defineMotion (async, returning Promise<Pos>) instead of defineAction. The capture-phase operator-pending interceptor (src/easymotion/operator-pending.ts) has been removed — operator-pending and visual mode work natively through the fork's async motion dispatch.
  • EasyMotion module refactored from single easymotion.ts (243 lines) into 6 focused files: register.ts (data-driven registration), targets.ts (direction-aware target finding), labels.ts (SCTree algorithm), overlay.ts (DOM rendering with dimming and re-render support), keypress.ts (key capture with 2-char narrowing), types.ts (interfaces)
  • <leader><leader>w, <leader><leader>j, <leader><leader>f are now forward-only, matching vim-easymotion parity. Previously these scanned the entire visible viewport regardless of cursor position.
  • registerEasyMotion() now accepts a dimming parameter and uses a data-driven EASYMOTION_DEFS array for registration instead of per-motion imperative code
  • showOverlay() returns an OverlayHandle with updateLabels() for dynamic re-rendering during 2-char label narrowing
  • waitForLabel() replaces waitForKey() as the primary label capture function, supporting multi-char labels, backspace reset, and narrowing callbacks
  • Removed test/specs/easymotion-motions.e2e.ts — superseded by easymotion-comprehensive.e2e.ts with correct async test patterns for char-input motions
  • Fork dependency — @replit/codemirror-vim now references https://github.com/saberzero1/codemirror-vim.git instead of a local file path, enabling CI/scanner environments to install without local checkouts
  • reportUnusedDisableDirectives set to off in eslint config to avoid conflicts between local and scanner lint rule sets
  • Added Obsidian to sentence-case brands list in eslint config

Documentation

  • KNOWN_LIMITATIONS.md: EasyMotion operator-pending rewritten — now uses async motions natively instead of capture-phase interceptor
  • KNOWN_LIMITATIONS.md: added 8 behavioral deviation entries for fork fixes (dd cursor, J whitespace, di{} multiline, dj/dk boundary, :s cursor, % strings, db cross-line, dw cursor)
  • KNOWN_LIMITATIONS.md: added "DOM keyboard events not routed after settings reload" and "EasyMotion visual mode label selection via DOM events" sections
  • AGENTS.md: added codemirror-vim fork section with dual-vim architecture documentation
  • README.md: added "Recommended setup" section explaining benefits of disabling built-in vim
  • DIFFERENCES.md (fork): comprehensive rewrite documenting all behavioral fixes and infrastructure changes

Full Changelog: 0.9.0...0.10.0

Don't miss a new motions release

NewReleases is sending notifications on new releases.