github saberzero1/motions 0.53.0

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

Fixed

  • Which-key descriptions not showing for keymaps set via Lua — vim.keymap.set and vim.obsidian.leader.set with a desc option showed raw action names (lua-action-0), command strings (:Oil<CR>), or internal function names (harpoonSelect1) instead of the user's description. The codemirror-vim fork normalizes literal space characters to <Space> notation in key strings (e.g., " ff" → "<Space>ff"), but the which-key overlay stored and looked up label keys using unnormalized literal spaces — all lookups missed. Additionally, the leader-only which-key mode never triggered with space as leader because the vim-keypress event emits "<Space>" but the overlay compared against the raw " " character. (#58)
    • Plugin: src/ui/which-key.ts (normalizeVimKey() function mirroring the fork's normalizeKeyString, normalizedLeaderKey field for key event comparison, normalized lookups in showLeaderBindings/showCompletions/onKeyPressLeaderOnly), src/main.ts (rebuildWhichKey() normalizes all commandLabels and groupLabels map keys from settings, vimrc, and Lua sources)
  • vim.opt.clipboard silently ignored in init.lua — setting vim.opt.clipboard = "unnamed" or "unnamedplus" in init.lua had no effect. The Lua vim.opt handler only routed options through the KNOWN_SET_OPTIONS table, but clipboard was special-cased in the vimrc loader and missing from that table. Yanks never synced to the system clipboard when configured via Lua. Same issue affected vim.opt.textwidth. (#56)
    • Plugin: src/vimrc/loader.ts (SideEffectOpt type, clipboard/textwidth/guicursor added to KNOWN_SET_OPTIONS), src/lua/api.ts (special-case blocks removed, unified KNOWN_SET_OPTIONS path), src/main.ts (initial settings load from saved values), src/lua/loader.ts (setOption callback)
  • Settings-based clipboard and textwidth not restored on plugin restart — if a user set clipboard or textwidth via the Settings UI, the value was saved to disk but not re-applied to the vim engine on the next Obsidian startup. The saved this.settings.clipboard and this.settings.textwidth were never pushed to vim.setOption() during plugin load. Fixed by applying saved side-effect options after registerVimOptions().
    • Plugin: src/main.ts (initial settings loop using KNOWN_SET_OPTIONS sideEffects)

Changed

  • Vim option architecture: SideEffectOpt type — options that require side effects beyond this.settings[key] = value (clipboard, textwidth, guicursor) are now declared in the KNOWN_SET_OPTIONS table with a sideEffect type and an apply() callback. Previously, these options were special-cased with separate if blocks in both the vimrc loader and the Lua vim.opt handler — adding a new side-effect option required touching 2-3 files manually, and missing one path caused silent failures. Now there is a single declaration point. The vimrc loader, Lua handler, and initial settings load all route through the same table-driven path.
    • Plugin: src/vimrc/loader.ts (SideEffectOpt interface, applyKnownSetOption sideEffect handling, special-case blocks removed), src/lua/api.ts (unified KNOWN_SET_OPTIONS path)

Added

  • Snippets — VS Code-compatible snippet expansion with tabstop navigation, linked mirrors, variable resolution ($CURRENT_YEAR, $TM_FILENAME, $UUID, etc.), and context-aware filtering (prose/code/frontmatter). Ships 40+ Obsidian-adapted snippets (headings, callouts, wikilinks, tables, frontmatter, math, date/time). Three trigger mechanisms: CM6 completion menu, Tab expansion (vim-native), and ex commands (:snippet name, :snippets picker). Bundled snippets toggleable via settings.
  • User snippet directory — load custom VS Code JSON snippet files from a configurable directory. Supports vault-relative and absolute paths (with ~ expansion, desktop only). User snippets override bundled snippets on prefix collision.
  • Snippet Lua DSL — LuaSnip-inspired vim.snippet.* API: s(), t(), i(), c(), rep(), fmt() for static snippets that compile to VS Code JSON at load time. f() (function nodes), d() (dynamic nodes), sn() (snippet nodes), r() (restore nodes) for reactive snippets that execute Lua functions via fengari at edit time.
  • Snippet context filtering — snippets can be restricted to specific editing contexts ("prose", "code:js", "code:*", "frontmatter") via a "context" field in JSON or the context option in Lua DSL.
  • Choice node cycling — Ctrl+N/Ctrl+P cycle through choice options (${1|a,b,c|}) on active snippet fields.
  • Snippet picker — :snippets opens the telescope-style fuzzy finder with snippet preview. :snippet name expands by name.
  • @codemirror/autocomplete fork — recursive descent snippet parser replacing CM6's regex parser, supporting choice nodes, nested placeholders, transforms (parsed, not applied), and bare $1 syntax. Fork at saberzero1/autocomplete.
  • 4 new settings: Enable snippets, Bundled snippets, Snippet directory, Trigger mode
  • 4 new vimrc set options: snippets, snippetbundled, snippetdir, snippettrigger
  • 13 new vim.snippet.* Lua API functions
  • Plugin files: src/snippets/ (14 files), src/lua/snippet-api.ts, src/snippets/dynamic-bridge.ts
  • Fork files: ~/Repos/autocomplete/src/snippet.ts (parser), ~/Repos/autocomplete/src/index.ts (exports)

Tests

  • 9 unit tests in test/unit/which-key.test.ts: normalizeVimKey() — space conversion, idempotence, angle-bracket preservation, mixed notation
  • 4 e2e regression tests in test/specs/lua-space-leader.e2e.ts: which-key descriptions with space leader — string command desc, function callback desc, all mode desc, vim.obsidian.leader.set desc
  • 11 new e2e tests in test/specs/lua-config.e2e.ts:
    • vim.opt.clipboard = "unnamed" applies from init.lua (1 test)
    • yy/yw/dd populate + register when clipboard set via Lua (3 tests)
    • vim.opt.textwidth and vim.opt.tw alias from init.lua (2 tests)
    • Dual-config override precedence: Lua overrides vimrc for clipboard, textwidth, scrolloff (3 tests)
    • Error resilience: unknown Lua option preserves vimrc clipboard; invalid textwidth (-5) preserves vimrc value (2 tests)
  • 7 e2e spec files (22 passing, 5 skipped) covering expansion, tabstops, variables, context, f()/d() nodes, static regression
  • 15 LuaSnip golden comparison unit tests (extracted from LuaSnip test suite commit 0abc8f3)
  • 359 total unit tests passing

Documentation

  • docs/features/snippets.md (new feature page)
  • docs/features/index.md, docs/reference/keybindings.md, docs/configuration/settings.md, docs/features/ex-commands.md, docs/configuration/vimrc.md, docs/configuration/lua-config.md (updated)
  • AGENTS.md (fork dependency + page ownership)
  • KNOWN_LIMITATIONS.md (7 limitation entries)

Full Changelog: 0.52.0...0.53.0

Don't miss a new motions release

NewReleases is sending notifications on new releases.