Added
- Animated cursor: cross-cell position handoff — when navigating between table cells via
h/j/k/l, a token-based handoff seeds the new cell'sCursorControllerwith the previous cell's screen position via theAnimatedCursorManagersingleton. The handoff infrastructure is in place but the canvas transition animation is not visible due to CSS stacking contexts (the canvas atposition: fixedon.app-containerrenders behind table cell content). The native vim cursor (BlockCursorPlugin) serves as the steady-state renderer inside cells. See KNOWN_LIMITATIONS.md for details.- Plugin:
src/vim/animated-cursor/manager.ts(CellCrossingHandoffinterface,createCrossingToken/storeCrossingHandoff/consumeCrossingHandoffmethods,signalCellCrossing/getPendingCrossingToken/clearPendingCrossingTokenmodule-level functions) - Plugin:
src/vim/animated-cursor/controller.ts(cellTransitionActiveflag, crossing token consumption in constructor, position handoff in destroy, cell-aware tick/update that skips canvas drawing when no transition is active) - Plugin:
src/vim/table-cell-motions.ts(signalCellCrossing()call inscheduleCrossing) - Fork:
~/Repos/codemirror-vim/src/block-cursor.ts(table cell override documented in DIFFERENCES.md) - Styles:
styles.css(animated cursor canvas z-index bumped from 5 to 15)
- Plugin:
Changed
- Table editing: migrated to native Obsidian table editor — the plugin no longer suppresses Obsidian's
cm-table-widgetor provides custom cell editors. In Live Preview, Obsidian's native table editor handles cell editing, pipe escaping, wikilinks, cursor positioning, and<br>conversion. Vim is injected into native cell editors viaregisterEditorExtension(). ThetableWidgetModesetting is simplified from 4 values (off/cursor/always/embedded) to 2 (native/raw). Old values are automatically migrated.- Removed:
src/vim/table-widget-suppressor.ts(RangeSetBuildermonkey-patch) - Removed:
src/vim/table-render-widget.ts(custom widget) - Removed:
src/vim/table-nav-controller.ts(custom nav state machine) - Removed:
src/vim/table-cell-editor.ts(custom cell editors) - Removed:
src/vim/table-embedded-editor.ts(configuration bridge) - Added:
src/vim/table-nav-overlay.ts(nativeTableEditorAPI overlay) - Added:
src/vim/native-table-adapter.ts(typed abstraction layer) - Added:
src/types/table-editor.d.ts(runtime-discovered typings for 55 native methods)
- Removed:
Fixed
- Escape in hint mode exits embedded vim editor — pressing Escape to dismiss hint mode while inside an embedded vim editor (textarea vim overlay, Oil explorer, table cell editor) also exited the embedded editor. Root cause: Obsidian's
Scopekeymap handlers fire independently of DOM event propagation —stopPropagation()in hint mode's capture-phase listener does not prevent the Scope handler from receiving the event. The embedded editor's Scope handler checkedisVimIdle()(which returnstrueduring hint mode, since hint mode is a plugin-level overlay, not a vim state) and calledonEscape(). Fixed by adding a guard in the embedded editor's Escape handler that checksisHintModeActive(),isEasyMotionActive(), andisFlashActive()before evaluatingisVimIdle(). (#126)- Plugin:
src/editors/embeddable-editor.ts(Scope Escape handler — modal overlay active guard beforeisVimIdle()check)
- Plugin:
- Wikilinks in table cells work correctly — cursor displacement when typing
[[in table cells is fixed. The native editor handles wikilink rendering at the decoration layer, eliminating the sub-CM6 cursor displacement that affected the old custom widget. - Pipe character (
|) no longer swallowed in table cells — the native editor automatically escapes|as\|in the document source. Previously, Obsidian's DOM-level table editor intercepted|before CM6's input pipeline. <br>conversion handled natively — newlines in table cells are automatically converted to/from<br>by the native editor. ThecellBrToNewline/cellNewlineToBrutilities are removed.- Embedded table: Obsidian shortcuts (Ctrl+P, Cmd+O) now work in cell selection mode — modifier key combos in table-nav mode now call
e.stopPropagation()to prevent vim'seventObservers.keydownfrom consuming them as cursor movement, then manually feed the event to Obsidian's keymap system viaapp.keymap.onKeyEvent(e). This two-step approach blocks vim (which would process<C-p>as cursor-up) while still triggering Obsidian's hotkey bindings (command palette, file switcher, custom hotkeys). Uses the unofficialKeymap.onKeyEventAPI fromobsidian-typings. (#120)- Plugin:
src/vim/table-nav-controller.ts(handleTableNavKey—stopPropagation+app.keymap.onKeyEventfor modifier combos)
- Plugin:
- Embedded table: ex command dialog keys no longer consumed by table-nav — when vim's ex command dialog is open (after pressing
:), table-nav keys likeh,j,k,l,a,i,care no longer intercepted by the table-nav handler. The handler now checksadapter.state.dialogand returns early when a dialog is active. (#120)- Plugin:
src/vim/table-nav-controller.ts(handleTableNavKey—adapter.state.dialogcheck)
- Plugin:
- Insert mode escape sequence and other vim engine settings not applied after restart — six vim engine settings (insertmodeescape, insertmodeescapetimeout, operatorshadowtimeout, tabstop, shiftwidth, expandtab) configured via the Settings UI were not synced to the vim engine on plugin load. Only clipboard, textwidth, and pcre were synced at startup. The remaining settings were stored in
data.jsonbut never pushed tovim.setOption()during initialization, so they silently reverted to defaults on every Obsidian restart. The vimrc/Lua code path was unaffected because it callsvim.setOption()directly. Additionally, on Obsidian 1.13+, the declarative settings system (setControlValue) did not forward any of the 9 vim engine settings tovim.setOption()— only the pre-1.13 imperativeonChangehandlers did. (#125)- Plugin:
src/main.ts(added init sync for insertmodeescape, insertmodeescapetimeout, operatorshadowtimeout, tabstop, shiftwidth, expandtab afterregisterVimOptions()) - Plugin:
src/settings.ts(VIM_OPTION_KEYSstatic set;setControlValueforwards vim engine settings tovim.setOption()withsetClipboardOption/setTextwidthside effects)
- Plugin:
Tests
- 1 regression test for hint mode Escape in
test/specs/textarea-vim.e2e.ts(issue #126): Escape in hint mode dismisses hint overlay but does not exit the textarea vim overlay — verified to fail without the modal overlay guard - 1 regression test for modifier combo in
test/specs/table-cell-vim-mode.e2e.ts: modifier combo does not move cursor during cell selection - 1 regression test for ex dialog in
test/specs/table-cell-vim-mode.e2e.ts: keys with table-nav meaning do not change active cell when ex dialog is open (verified to fail without dialog check)
Documentation
CHANGELOG.mdKNOWN_LIMITATIONS.md: Added hint mode Escape fix to textarea vim Escape behavior section (#126)AGENTS.md: Updated embeddable-editor description with modal overlay active guardCONTRIBUTING.md: Updated embeddable-editor description with modal overlay active guarddocs/features/hint-mode.md: Added note about embedded editor Escape isolationKNOWN_LIMITATIONS.md: Updated vim engine settings section — all 9 settings now synced at init (was 3); added declarative settings forwarding fix for Obsidian 1.13+ (#125)KNOWN_LIMITATIONS.md: Added animated cursor cross-cell transition as known limitation in table cell vim modality sectionCONTRIBUTING.md: Addedtable-cell-motions.tsandtable-cell-cursor-guard.tsto codebase structure; updatedmanager.tswith cross-cell handoff API; updatedcontroller.tswith cell transition architectureAGENTS.md: Updated animated cursor page ownership (unchanged —features/animated-cursor.md)docs/features/animated-cursor.md: Updated embeddable editors section with cross-cell transition details and known limitationdocs/features/tables.md: Added animated cursor note to cell editor section- Fork
DIFFERENCES.md: Added table cell override section documenting BlockCursorPlugin's unsuppress behavior for.cm-table-widgeteditors
Full Changelog: 0.109.1...0.110.0