diff --git a/CHANGELOG.md b/CHANGELOG.md index be3a671..1a5bcea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,13 +10,15 @@ Format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). Version ### Added -- `/vim` slash command to toggle vim mode on/off. State is persisted via `api.kv` so the preference survives restarts. When disabled, all keys pass through unmodified. +- `/vim` toggle command to disable/enable vim mode. Persisted across restarts. +- Startup toast when vim is disabled so users know why keybindings aren't active. ### Fixed -- `api.kv.set` call in `/vim` toggle now uses optional chaining (`api.kv?.set?.()`) to avoid crashing on OpenCode versions without `api.kv`. -- Disabled check moved before autocomplete handling so Escape/Enter are not intercepted when vim is disabled. -- Toggling vim off now resets to insert mode and clears pending operator/char/count state, preventing stale state on re-enable and fixing cursor style. +- Optional chaining on `api.kv.set` to avoid crashes on older OpenCode versions. +- Escape/Enter no longer intercepted when vim is disabled. +- Toggling vim off resets mode and clears pending state. +- `:vim` palette title uses `:` prefix, consistent with `:q`/`:quit`/`:wq`. ## [0.13.0] — 2026-06-09 diff --git a/src/index.ts b/src/index.ts index 214e56d..b3e3791 100644 --- a/src/index.ts +++ b/src/index.ts @@ -36,6 +36,9 @@ const plugin: TuiPluginModule = { // Load persisted disabled state const persistedDisabled = (await api.kv?.get?.("vimcode.disabled")) as boolean | undefined; state.disabled = persistedDisabled ?? false; + if (state.disabled) { + api.ui?.toast?.({ message: "Vim mode disabled (use /vim to re-enable)", variant: "info", duration: 3000 }); + } // Track whether the previous key was the leader, so the follow-up // key also passes through to OpenCode's leader system. @@ -200,44 +203,24 @@ const plugin: TuiPluginModule = { // Register all commands via registerLayer (migrated from the deprecated // api.command?.register API). Commands appear in the command palette and // are accessible as slash commands. + const exitRun = async () => { + setTimeout(() => api.keymap.dispatchCommand("app.exit"), 0); + }; + const exitCommands = ["q", "quit", "wq"].map((cmd) => ({ + name: `vimcode.${cmd}`, + title: `:${cmd}`, + category: "Vim", + namespace: "palette", + desc: cmd === "wq" ? "Exit OpenCode (write and quit)" : "Exit OpenCode", + slashName: cmd, + run: exitRun, + })); api.keymap.registerLayer?.({ commands: [ - { - name: "vimcode.q", - title: ":q", - category: "Vim", - namespace: "palette", - desc: "Exit OpenCode", - slashName: "q", - run: async () => { - setTimeout(() => api.keymap.dispatchCommand("app.exit"), 0); - }, - }, - { - name: "vimcode.quit", - title: ":quit", - category: "Vim", - namespace: "palette", - desc: "Exit OpenCode", - slashName: "quit", - run: async () => { - setTimeout(() => api.keymap.dispatchCommand("app.exit"), 0); - }, - }, - { - name: "vimcode.wq", - title: ":wq", - category: "Vim", - namespace: "palette", - desc: "Exit OpenCode (write and quit)", - slashName: "wq", - run: async () => { - setTimeout(() => api.keymap.dispatchCommand("app.exit"), 0); - }, - }, + ...exitCommands, { name: "vimcode.vim", - title: "/vim", + title: ":vim", category: "Vim", namespace: "palette", desc: "Toggle vim mode on/off",