Fixed
- Disabling workspace navigation disables all global keybindings — turning off Settings → Vim Motions → Navigation → Workspace navigation also disabled the
:ex command line in reading view,vim.obsidian.keymap.setmappings, and hint mode global hotkeys. Root cause: theGlobalKeyHandlerandGlobalMappingRegistrywere only instantiated whenenableWorkspaceNavwas true, and all three interception gates (shouldInterceptContent,shouldInterceptHints,shouldInterceptStructural) returned false when the setting was disabled. Fixed by always creating the global key handler on desktop and moving theenableWorkspaceNavguard from the interception layer to the mapping registration layer — only scroll, tab, and pane navigation keys are conditional on the setting;:, hint mode, and user global keymaps are always registered. (#164)- Plugin:
src/workspace/global-key-handler.ts(removedenableWorkspaceNavguard fromshouldIntercept*methods) - Plugin:
src/workspace/global-defaults.ts(addedopts.enableWorkspaceNavparameter to conditionally register workspace-nav-specific keys) - Plugin:
src/main.ts(always createGlobalKeyHandler/GlobalMappingRegistryon desktop)
- Plugin:
- Hint mode
<leader><leader>hmapping reappears after settings change —vim.keymap.del("n", "<leader><leader>h")in init.lua was silently undone by any subsequent settings change becausereloadFeatures()re-registered the hardcoded mapping without re-applying Lua map operations. Additionally, the mapping was registered without an explicitcontext: 'normal', making mode-specificvim.keymap.delunable to target it (codemirror-vim'sunmaprequires exact context match). Fixed by (1) callingapplyLuaMaps()at the end ofreloadFeatures()so Lua unmaps are re-applied after built-in mappings, and (2) registering the hint mode mapping with{ context: 'normal' }. (#162)- Plugin:
src/main.ts(applyLuaMapscall inreloadFeatures,context: 'normal'on hint modemapCommand)
- Plugin:
- Leader-based
mapCommandcalls missingcontext: 'normal'— picker (<leader>ff/fg/fb/...), harpoon (<leader>ha/hp/hn/hN,<leader>1–<leader>9), and workspace navigation (<leader>rn/rb/ra,grn/grr/gra) leader mappings were registered without an explicit mode context. This madevim.keymap.del("n", ...)unable to remove them because codemirror-vim'sunmap(lhs, 'normal')requirescontext === 'normal'to match. Added{ context: 'normal' }to all leader-based actionmapCommandcalls. EasyMotion motions were intentionally left without context because they must work in operator-pending and visual modes (d<leader><leader>w,v<leader><leader>j).- Plugin:
src/main.ts(picker and harpoon leader mappings) - Plugin:
src/workspace/navigation.ts(<leader>rn/rb/raandgrn/grr/gramappings)
- Plugin:
vim.keymap.delunable to remove context-less mappings per-mode —Vim.unmap(lhs, 'normal')silently failed on mappings created bymapCommand()or:mapwithout a mode prefix, because the entry hadcontext === undefinedand the strict equality check (undefined === 'normal') never matched. The only removal paths wereremoveMapCommand(keys)orunmap(lhs, undefined), both of which remove from all modes. Fixed in the fork:unmapnow falls back to splitting a context-less entry into per-mode entries for the remaining modes when a mode-specific unmap is requested, matching Neovim's:nunmapon a:map-created mapping. Also fixedmapclear's context-splitting mode set from['normal', 'insert', 'visual']to['normal', 'visual', 'operatorPending']to match Neovim's:mapsemantics (:mapcovers normal+visual+operatorPending, not insert).- Fork:
~/Repos/codemirror-vim/src/vim.js(unmapcontext-less entry splitting,mapclearmode set fix)
- Fork:
- Command palette lags ~1 second in visual-line mode — opening the command palette from visual-line mode caused a visible delay. Root cause: the
wrapCheckCallbackwrapper calledwithExpandedSelectionfor every command'scheckCallback(true)availability check, dispatching two CM6 transactions (expand + restore) per command. With 200+ commands, this produced 400+ synchronous CM6 dispatches while the palette rendered. Fixed by skippingwithExpandedSelectionfor the checking path (checkCallback(true)) — theVisualLineSomethingSelectedPatchalready ensuressomethingSelected(),getCursor(), andlistSelections()return the correct visual-line range, so availability checks work without native CM6 selection expansion. The executing path (checkCallback(false)) still useswithExpandedSelection. (regression of #157, #163)- Plugin:
src/vim/visual-line-command-fix.ts(skipwithExpandedSelectionforcheckCallback(true))
- Plugin:
- Stale visual-line selection cache causes RangeError —
lastVisualLineSelandpendingVisualLineSelcached line numbers from a previous visual-line selection could exceed the document length after the editor content was replaced with a shorter document (e.g., between e2e tests or:ecommands). The stale cache causeddoc.line(N)to throwRangeError: Invalid line number N in M-line document. Fixed by validating cached selection line numbers against the current document length before use; stale caches are invalidated instead of producing errors.- Plugin:
src/vim/visual-line-command-fix.ts(isSelInBoundsvalidation insomethingSelected,getSelection,replaceSelection)
- Plugin:
Changed
- E2E test Obsidian version pinned to 1.13.7 —
wdio.conf.mtsbrowserVersionchanged from'latest'to'1.13.7'. Obsidian 1.13.8 is a mobile-only release (APK only, no desktop asar), causing the test runner to fail with "No compatible installers available."
Tests
- 3 regression tests in
test/specs/settings-reload.e2e.tsfor #164 (global key handler/registry existence with workspace nav disabled) and #162 (Lua keymap deletions survivereloadFeatures)
Documentation
CHANGELOG.mdKNOWN_LIMITATIONS.md: updated workspace navigation section to reflect decoupled architecture; updated yank-ring workspace navigation dependency note; updated three-gate description; updatedkeymap.del + Qdeviation andremoveMapCommanddescriptionKNOWN_LIMITATIONS.md: updatedwrapCheckCallbackdescription withcheckCallback(true)optimization (#163)AGENTS.md: updated fork description withunmapper-mode splitting andmapclearmode set fix- Fork:
~/Repos/codemirror-vim/DIFFERENCES.md: added "Per-modeunmapof context-less mappings" section; updatedremoveMapCommanddescription
Full Changelog: 0.140.0...0.141.0