Fixed
- Textarea vim overlay re-activates immediately after Escape exit — pressing Escape in normal mode tore down the overlay and called
originalEl.focus(), which triggered thefocusinlistener and re-created the overlay in insert mode after the 150ms debounce. Users saw a brief flash of the textarea before being placed back in insert mode, making it impossible to return to the modal context. Fixed by adding arecentlyExitedguard (WeakRef+ 250ms cooldown) that suppresses thefocusinhandler for the textarea that was just exited. After the cooldown, the textarea can be re-activated by clicking into it again. (#69)- Plugin:
src/vim/textarea-vim-manager.ts(recentlyExitedWeakRef guard,markRecentlyExitedcooldown)
- Plugin:
- Lua text objects lost after
reloadFeatures()—vim.textobject.add()registrations from.obsidian.init.luawere silently discarded becauseloadLuaConfigInternal()calledreloadFeatures()after Lua evaluation, destroying theVimRegistrationinstance that held the keybindings. Fixed by persisting text object specs inluaTextObjectSpecs[]and re-registering them viareregisterLuaTextObjects()afterreloadFeatures()completes.- Plugin:
src/main.ts(luaTextObjectSpecs,registerLuaTextObject,reregisterLuaTextObjects)
- Plugin:
Added
- Subword motions (spider.nvim-style) —
w/b/e/geoverride stopping at camelCase, snake_case, and kebab-case word boundaries. Opt-in viaset subword/ Settings → Vim features → Subword motions. 10,000-char performance guard falls back to standard word motions on pathological lines.- Plugin:
src/util/subword.ts(shared boundary detection),src/motions/subword.ts(4 motion variants)
- Plugin:
- General-purpose text objects — 6 new text objects complementing the existing 13 Markdown-specific ones:
iS/aS(subword segment),in/an(numeric literal with sign/decimal),iq/aq(nearest quote pair on line),iD/aD(wikilink[[...]]with nesting),gL(forward-seeking URL),i,/a,(comma-separated argument with nesting). All work with operators (d,c,y) and visual mode.- Plugin:
src/text-objects/{pair-util,subword,number,any-quote,double-bracket,url,argument}.ts
- Plugin:
- Enhanced increment/decrement (dial.nvim-style) —
<C-a>/<C-x>extended to cycle: markdown checkboxes ([ ]↔[x]), booleans (true↔false, case-preserved), hex colors (component-wise R/G/B, clamped 0–255), dates (YYYY-MM-DDwith rollover), CSS values (preserving unit), and integers. Priority-ordered rules (first match wins). Opt-in viaset dial/ Settings → Vim features → Enhanced increment/decrement. Falls back to default<C-a>/<C-x>when no rule matches.- Plugin:
src/actions/{dial-rules,dial,register-dial}.ts
- Plugin:
- Custom text objects via Lua —
vim.textobject.add(keys, spec)andvim.textobject.del(keys)API for defining custom text objects from.obsidian.init.lua.vim.gen_spec.pair(open, close, opts?)generates pair-matching specs with nesting and multi-line support. Keys must start withi(inner) ora(around). Invalid inputs produce error notices.- Plugin:
src/lua/textobject-api.ts
- Plugin:
- External grep binary integration — optional native ripgrep or GNU grep binary for the picker's grep/live-grep sources. Supports
rg --json(structured output) andgrep -rn(file:line:content format). Desktop-only with automatic fallback to in-memory search on mobile or binary failure. Circuit breaker (3 errors in 60s → auto-disable). Process cancellation on new query.- Plugin:
src/picker/sources/ripgrep-process.ts, settings:ripgrepEnabled,ripgrepBinaryPath,ripgrepArgs,grepMode
- Plugin:
Tests
- 37 unit tests in
test/unit/subword.test.ts: boundary detection (13 patterns), motion logic (20 cases including cross-line, count, performance guard) - 45 unit tests in
test/unit/text-objects-extended.test.ts: all 6 text objects with inner/around, edge cases, nesting - 31 unit tests in
test/unit/dial.test.ts: all 6 rules individually + priority ordering + tryDial integration - 26 unit tests in
test/unit/lua-textobject-api.test.ts: asymmetric/symmetric pair matching, nesting, multi-line, scanLimit - 21 unit tests in
test/unit/ripgrep-process.test.ts: JSON/grep output parsing, arg building, error classification - 10 e2e tests in
test/specs/subword-motions.e2e.ts: navigation, operators, snake/kebab, count, setting toggle - 11 e2e tests in
test/specs/text-objects-extended.e2e.ts: all text objects with delete/change operators - 9 e2e tests in
test/specs/dial.e2e.ts: all rule types, count prefix, no-match fallback, setting toggle - 5 e2e tests in
test/specs/lua-textobject.e2e.ts: custom pairs (single-char, multi-char, nested), error handling - 3 e2e tests in
test/specs/ripgrep.e2e.ts: conditional skip (binary availability)
Documentation
CHANGELOG.md: Added textarea re-activation prevention fixKNOWN_LIMITATIONS.md: Textarea re-activation after Escape → Fixed (recentlyExited guard)
Full Changelog: 0.68.0...0.69.0