Added
- Plugin auto-fetch system —
vim.plugins.add()now supports automatic fetching of Neovim plugins from GitHub. Downloads tarball archives, extracts them tolua/, and manages a lock file (lua/.plugin-lock.json) for version pinning. Supports branch, tag, and commit pinning. Atomic staging writes tolua/.staging/ensure vault integrity. Configurable viapluginAutoFetchsetting (Advanced page).- Plugin:
src/lua/plugin-fetch.ts(download and extraction logic) - Plugin:
src/lua/plugin-store.ts(atomic writes and lock file management) - Plugin:
src/lua/tar.ts(synchronous tar parser) - Plugin:
src/lua/api.ts(extendedvim.plugins.addwith fetch triggering) - Plugin:
src/lua/loader.ts(wired fetch callback) - Plugin:
src/settings.ts(newpluginAutoFetchsetting)
- Plugin:
require()init.lua fallback —require("name")now trieslua/name/init.luaiflua/name.luais not found. Matches Neovim's module resolution behavior and enables multi-file plugins.- Plugin:
src/lua/package.ts(updatedpackage.pathand search logic)
- Plugin:
Changed
- Lua sandbox:
rawget/rawset/rawequalre-enabled — these standard Lua functions are now available in the sandbox, matching Neovim's Lua environment. Previously disabled as a sandboxing measure, but this preventedvim.is_callablefrom detecting callable tables and broke compatibility with Neovim plugins that userawget/rawset.- Plugin:
src/lua/engine.ts(removed from disabled globals list)
- Plugin:
Fixed
- Operator-pending mode context —
modeToContext('o')now correctly returns'operatorPending'instead of'normal'. Fixes keymap collisions where operator-pending text objects shadowed normal mode mappings (e.g.,gc/gcc).- Plugin:
src/lua/api.ts(context mapping fix)
- Plugin:
- Fork: Backtracking dispatch — the codemirror-vim fork now supports backtracking when a longer partial match fails. Deferring a shorter full match (e.g., flash
smotion) for a longer partial (e.g., surrounds<char>) no longer loses the motion if the partial match fails or times out. Replays the suffix viadoKeyToKey.- Fork:
~/Repos/codemirror-vim/src/vim.js(backtracking logic inhandleKeyNonInsertMode)
- Fork:
- Fork: Backtracking deferral exclusion rules — the backtracking deferral in
matchCommandno longer falsely defers built-in keys (i,a,s,S,d,y,c,<,>) when text-object motions, linewise shortcuts, surround actions, or<leader>keymaps share a string prefix. Four exclusion rules prevent false positives:_isDefaultentries (built-in keymaps), special-key false prefix (<vs<leader>), motions extending non-motions (ilvsi), andoperatorPendingactions without an active operator (s<char>vss). Without this fix, pressingiorain normal mode was deferred by ~1 second instead of immediately entering insert mode.- Fork:
~/Repos/codemirror-vim/src/vim.js(exclusion rules inmatchCommand) - Fork:
~/Repos/codemirror-vim/DIFFERENCES.md(documented all 4 exclusion rules)
- Fork:
- Lua function-callback keymaps survive view plugin recreation —
applyLuaMapsreverted to usethis.registration?.defineAction()instead ofvim.defineAction()directly. TheVimRegistrationpersistence layer re-applies action registrations when the CM6 view plugin is recreated (e.g., during vim mode toggle), preventing Luavim.keymap.setfunction callbacks from silently stopping.- Plugin:
src/main.ts(revertedapplyLuaMapsfunction-callback path)
- Plugin:
Tests
- CI test plugin pre-fetch — e2e tests no longer depend on runtime GitHub fetches. A
scripts/fetch-test-plugins.shscript downloads plugin tarballs before tests run, driven bytest/fixtures/test-plugins.json. The CI workflow fetches plugins in a dedicated step on all platforms (Linux, macOS, Windows).loadMiniCommentskipsvim.plugins.add()when the plugin is pre-fetched; the fetch test is skipped when pre-fetched. - Updated
test/specs/lua-plugin-mini-comment.e2e.ts—loadMiniCommentdetects pre-fetched plugins and skipsvim.plugins.add(); fetch test guarded withthis.skip()when pre-fetched. - Added
pluginAutoFetchto excluded settings intest/unit/known-set-options.test.ts. - Added
vimHandleKeysSynchelper intest/helpers.ts— dispatches keys viaVim.handleKeyin a single synchronousexecuteObsidiancall with Escape prefix. SupportswaitForTimeoutflag for leader-key mappings that trigger Neovim-correctoperatorshadowtimeoutdeferral. - Updated
test/specs/lua-vim-v.e2e.tsto usevimHandleKeysSyncwithwaitForTimeout=truefor<leader>t/<leader>hmappings that have longer partials (table nav keymaps\tL,\tdd, etc.). - Updated
test/specs/lua-doc-examples.e2e.tssmart-go-to-top test to usevimHandleKeysSyncwithwaitForTimeout=true. - Updated
test/specs/lua-require.e2e.tsrawget/rawset tests — expectations changed from 86/87 to 90 to reflect intentional re-enabling.
Documentation
CHANGELOG.mdAGENTS.md: addedvimHandleKeysSyncto test helpers list, added fork backtracking description, added CI test plugin pre-fetch descriptionCONTRIBUTING.md: updatedsrc/lua/file tree with new fetch-related files, added test plugin pre-fetch documentationKNOWN_LIMITATIONS.md: marked plugin fetching as implemented; addedinit.luafallback note; updatedvim.is_callablenote (rawget no longer restricted); updated operator-prefix key dispatch section with backtracking deferralREADME.md: added plugin auto-fetch to features listdocs/configuration/settings.md: addedpluginAutoFetchsettingdocs/configuration/lua-config.md: updatedvim.plugins.addandrequire()sections
Full Changelog: 0.138.0...0.139.0