github saberzero1/motions 0.94.0

latest releases: 0.150.0, 0.149.0, 0.148.0...
one month ago

Fixed

  • Gutter settings ignored when set via vimrc or Luaset nonumber, set signcolumn=no, vim.opt.number = false, and other gutter-related settings (number, relativenumber, numberwidth, linenumbermode, cursorline, cursorlineopt, signcolumn, statuscolumn, foldcolumn) had no effect when configured via .obsidian.vimrc or .obsidian.init.lua. Root cause: vimrc/Lua overrides were in-memory only and never persisted, but gutter CM6 extensions are created at startup from persisted values. Fixed with a configOverrides persistence system: after vimrc/Lua loading, override values are captured and persisted in data.json. On next startup, configOverrides are merged on top of base settings before CM6 extensions are created, so gutters use the correct values from the start. Also added gutter reconfiguration calls to reloadFeatures() for in-session changes. (#101)
    • Plugin: src/main.ts (loadSettings — configOverrides extraction and merge; captureConfigOverrides — new shared capture method; saveSettings — persist configOverrides; reloadFeatures — gutter reconfiguration; softReloadVimrc — clear stale overrides and re-capture; clearSettingOverride — new helper)
    • Plugin: src/settings.ts (replaced vimrcOverrides?.delete with clearSettingOverride across all onChange handlers — covers both declarative and imperative paths, fixes missing luaOverrides deletion)
  • preVimrcSettings shallow copy — nested objects (cursorShapes, modePrompts, pickerKeymap) shared references with this.settings, causing saveSettings() to accidentally persist overridden cursor shapes. Fixed with deep copy.
    • Plugin: src/main.ts (line 677 — deep copy nested objects in preVimrcSettings snapshot)
  • Clipboard/textwidth falsely shown as "Set by vimrc" — the initial settings restoration at startup called onSettingOverride() for clipboard and textwidth, writing to vimrcOverrides even without a vimrc file. Fixed by using direct side-effect calls.
    • Plugin: src/main.ts (replaced onSettingOverride calls with direct setClipboardOption/setTextwidth calls)
  • Oil explorer loses focus after committing staged changes — after making changes in Oil (e.g., deleting a file) and committing with :w, the Oil editor lost focus when the confirmation dialog was confirmed or dismissed. Two bugs: (1) OilConfirmModal.onClose() never resolved the promise when the user pressed Esc to dismiss the modal, causing commit() to hang permanently. Fixed by adding a resolved guard — onClose() resolves false when no button was clicked. (2) After the confirmation dialog closed (via Confirm, Cancel, or Esc), focus was never returned to the Oil editor. Fixed by calling view.focusEditor() on both the cancel and commit paths. (#100)
    • Plugin: src/oil/manager.ts (OilConfirmModalresolved guard flag, onClose resolves on Esc dismissal; commitview.focusEditor() after confirm and cancel paths)
  • :sort cursor positioning:sort (and ranged :2,3sort) now positions the cursor at the first line of the sorted range, matching Neovim. Previously the cursor stayed at line 0 regardless of the sort range.
    • Fork: ~/Repos/codemirror-vim/src/vim.js (exCommands.sortcm.setCursor after replaceRange)
  • CTRL-V $ d cursor overshoot — after a block visual delete to end-of-line (CTRL-V jj $ d), the cursor column is now clamped to the remaining line length. Previously the cursor could land past the last character on shortened lines.
    • Fork: ~/Repos/codemirror-vim/src/vim.js (operators.delete — block visual cursor clamping)
  • Hint mode: modifier keydown event propagates to Obsidian handlers — pressing Ctrl alone during hint mode could trigger Obsidian's own key handlers because the modifier-only early return in waitForHintKey() did not call preventDefault() or stopPropagation(). The event leaked through to Obsidian's hotkey system via bubble-phase listeners, potentially causing side effects depending on the user's Obsidian configuration. Fixed by adding e.preventDefault() and e.stopPropagation() before the early return for modifier-only keys. (#98)
    • Plugin: src/ui/hint-mode.ts (waitForHintKey handler — preventDefault+stopPropagation on modifier-only keydown)
  • Hint mode: count prefix (2F) focus restoration races with async navigation — when using 2F on an internal link target, hintActivate() fired navigateWithJump() without awaiting it (via void), then setActiveLeaf(originalLeaf) ran synchronously. The async openLinkText() inside navigateWithJump could resolve after the focus restoration and steal focus back to the new tab — a race condition that manifested on slower machines or with heavier vaults. Similarly, duplicateLeaf() was fire-and-forgotten. Fixed by making hintActivate async and awaiting both navigateWithJump() and duplicateLeaf(). The createHintAction callback now awaits the action result before restoring focus, making the behavior deterministic. (#98)
    • Plugin: src/ui/hint-mode.ts (hintActivateasync, await navigateWithJump, await duplicateLeaf; hintOpenNew — returns Promise<boolean>; createHintActionasync callback, await action(), Promise.resolve() wrappers for sync actions)

Added

  • 27 new vimrc/Lua configurable options — the following settings were previously only configurable via the Settings UI and are now available via :set in vimrc and vim.opt in Lua: subword, picker, pickerleadermappings, pickermatcher, pickeromnisearch, pickertasks, pickerdataview, ripgrep, ripgreppath, ripgrepargs, grepmode, oil, oilhiddenfiles, oilconfirmdeletethreshold, oilsort, hinthotkey, undotreeposition, undotreeautoopen, imswitching, impreset, imbinarypath, imobtainargs, imswitchargs, imdefaultnormal, imrestorebehavior, imdefaultinsert. All options work identically across Settings UI, vimrc, and Lua.
    • Plugin: src/vimrc/loader.ts (27 new KNOWN_SET_OPTIONS entries)
  • Runtime invariant systeminvariant() (always-on, type-narrowing) and devAssert() (dev-only, stripped from production) helpers in src/util/invariant.ts. 21 invariants placed across 9 source files protecting mode transitions, dual-vim architecture, settings resolution, Lua engine lifecycle, extension cleanup, cursor state, and cell editor singleton. Violations are logged to console, rate-limited via Notice, and inspectable via the :violations ex command. __DEV__ build-time flag via esbuild define enables dev-only checks in development/watch builds and strips them from production.
    • Plugin: src/util/invariant.ts (new — invariant, devAssert, getViolations, clearViolations), src/types/globals.ts (new — __DEV__ global type declaration), esbuild.config.mjs (define option), vitest.config.ts (define option)
  • :violations ex command — displays accumulated invariant violations with timestamps. :violations! clears the violation log.
    • Plugin: src/workspace/commands.ts (:violations and :violations! registration)

Tests

  • 57 new unit tests across 5 new test files:
    • test/unit/invariant.test.ts (12 tests): invariant/devAssert helpers, violation cap, rate limiting, stack traces, shallow copy
    • test/unit/mode-tracker.test.ts (11 tests): getDialogPrefix, resolveMode logic
    • test/unit/dual-vim.test.ts (7 tests): bundled-vim lifecycle, bridge install/uninstall, invariant trigger
    • test/unit/settings-resolution.test.ts (16 tests): DEFAULT_SETTINGS completeness, settings merge, configMode migration, signcolumn migration, idempotency
    • test/unit/lua/lifecycle.test.ts (8 tests): sandboxed state creation/destruction, instruction guard, coroutine runner lifecycle
  • 3 expanded tests in test/unit/animated-cursor.test.ts: manager register/deregister, destroy clears all, MAX_CONTROLLERS warning
  • 70 new Neovim golden test cases (490 → 560): operator+motion combos (+28), visual mode operations (+15), insert mode operations (+12), ex command operations (+15)
  • 2 Neovim deviations closed (22 → 20): :2,3sort cursor positioning, CTRL-V $ delete to EOL cursor overshoot
  • 30 unit tests in test/unit/known-set-options.test.ts: KNOWN_SET_OPTIONS coverage guard (every non-excluded settings key has an entry, excluded keys list has no stale entries, no settingsKey points to non-existent setting), 27 new option entry validations (type, settingsKey, validValues)
  • 6 e2e tests in test/specs/gutter-vimrc-lua.e2e.ts: gutter settings via Lua config (enable/disable line numbers, enable/disable sign column, disable all gutter elements, hybrid line numbers)
  • 4 e2e tests in test/specs/oil-poc.e2e.ts (issue #100): oil retains focus after no-op commit, oil retains focus after confirmed destructive commit, oil retains focus after cancelled destructive commit, oil retains focus after Esc-dismissing the confirm modal
  • 3 e2e tests in test/specs/hint-mode.e2e.ts (issue #98): F on wikilink opens in new tab via command, openNew(2) on wikilink keeps focus on original leaf after first hint, Ctrl keydown stopped from propagating during hint mode

Documentation

  • CHANGELOG.md
  • KNOWN_LIMITATIONS.md: Marked gutter vimrc/Lua reconfiguration as fixed; marked preVimrcSettings shallow copy as fixed; marked clipboard/textwidth false override as fixed; updated set option scope section with configOverrides persistence; marked Oil focus loss after commit as fixed
  • docs/features/oil-explorer.md: Added focus retention after commit note
  • AGENTS.md: Updated hint mode page ownership with hinthotkey
  • README.md: Updated vimrc configurable settings count
  • CONTRIBUTING.md: Added configOverrides persistence and clearSettingOverride helper to conventions; updated vimrc loader description
  • docs/configuration/vimrc.md: Added 27 new options to vimrc tables; updated override behavior section with configOverrides persistence and gutter restart note
  • docs/configuration/lua-config.md: Added 27 new options to vim.opt table
  • KNOWN_LIMITATIONS.md: Marked :sort cursor and CTRL-V $ cursor deviations as fixed
  • CONTRIBUTING.md: Added invariant system to codebase structure, updated testing instructions for build:dev
  • AGENTS.md: Updated manual testing instructions for build:dev, added :violations command, updated golden test count and deviation count
  • README.md: Added npm run test:unit to development commands
  • DIFFERENCES.md (fork): Added :sort cursor positioning and block visual delete cursor clamping sections
  • docs/features/ex-commands.md: Added :violations and :violations! ex commands
  • KNOWN_LIMITATIONS.md: Updated hint mode modifier key fix with stopPropagation; updated count prefix focus fix with async hintActivate
  • AGENTS.md: Updated hint-mode.ts description with async hintActivate and modifier stopPropagation

Full Changelog: 0.93.0...0.94.0

Don't miss a new motions release

NewReleases is sending notifications on new releases.