Skip to content

Latest commit

 

History

History
335 lines (272 loc) · 10.1 KB

File metadata and controls

335 lines (272 loc) · 10.1 KB

OpenCode Vim Plugin

npm version Website

Adds Vim editing to the OpenCode prompt, including motions, operators, text objects, registers, visual mode, counts, undo/redo, and dot repeat.

Installation

Install globally:

opencode plugin @leohenon/opencode-vim-plugin --global

Important

Requires OpenCode 1.17.10 or newer.

Usage

Toggle via command palette > Toggle vim mode or slash command /vim.

Prompt controls

Unicode word boundaries are not yet supported.

Category Keys
Character / word h, j, k, l, w, b, e, W, B, E
Line / buffer 0, ^, _, $, gg, G
Display line gj, gk, g<Down>, g<Up>, g0, g^, g$
Matching / paragraph %, {, }
Find / till f, F, t, T, ;, ,
Scroll Ctrl+e, Ctrl+y, Ctrl+d, Ctrl+u, Ctrl+f, Ctrl+b
Insert / replace i, I, a, A, o, O, R
Character / line edit r, x, ~, s, S, J, C, D, dd, cc
Word changes cw, cb, ce, cW, cE, ciw, caw, ciW, caW
Word deletes dw, db, de, dW, dE, diw, daw, diW, daW
Quote changes ci", ca", ci', ca', ci` , ca`
Quote deletes di", da", di', da', di` , da`
Bracket changes ci(, ca(, ci[, ca[, ci{, ca{, ci<, ca<
Bracket deletes di(, da(, di[, da[, di{, da{, di<, da<
Find / till operators cf, cF, ct, cT, df, dF, dt, dT
Matching / paragraph operators c%, d%, c}, c{, d}, d{
Line boundary operators c0, c^, c$, d0, d^, d$, y0, y^, y$
Display line operators cgj, cgk, cg0, cg^, cg$, dgj, dgk, dg0, dg^, dg$, ygj, ygk, yg0, yg^, yg$
Line / word yanks yy, yw, ye, yW, yE, yiw, yaw, yiW, yaW
Quote yanks yi", ya", yi', ya', yi` , ya`
Bracket yanks yi(, ya(, yi[, ya[, yi{, ya{, yi<, ya<
Matching / paragraph yanks y%, y}, y{
Put / undo / repeat p, P, u, Ctrl+r, .
Visual selection v, V
Commands : :q

Numeric count prefixes are supported for motions and common operators.

Note

gg and G move within the prompt when the prompt has text. On an empty prompt, they dispatch OpenCode's session.first and session.last commands.

Configuration

Configure the plugin in tui.json:

{
  "plugin": [
    [
      "@leohenon/opencode-vim-plugin",
      {
        "enabled": true,
        "toggle_key": "ctrl+shift+v",
        "indicator": true,
        "vim_enter_submit": false,
        "vim_insert_after_submit": false,
        "vim_system_clipboard_register": false
      }
    ]
  ]
}

Options

For options beginning with vim_, the prefix may be omitted in plugin configuration.

Option Purpose
enabled Start with Vim mode enabled
vim_initial_mode Start in insert (default) or normal mode
toggle_key Keybind for Toggle vim mode
indicator Show the prompt Vim indicator
vim_enter_submit Submit with Enter from insert mode
vim_insert_after_submit Return to insert mode after submit
vim_system_clipboard_register Use the system clipboard as Vim register
vim_langmap Map non-English keys or simple aliases
vim_normal_leader Leader key for normal keybinds
normal_keybinds Extra keybinds active only in Vim normal mode
keybinds["vim.normal"] Nested normal-mode keybind configuration
vim_escape_sequence Use a two-key escape sequence like jk

Note

Unsupported OCV options: vim_line_motions

Initial mode

Vim mode starts in insert mode by default. To start in normal mode instead, use:

{
  "plugin": [
    [
      "@leohenon/opencode-vim-plugin",
      {
        "enabled": true,
        "vim_initial_mode": "normal"
      }
    ]
  ]
}

Mode-scoped keybinds

Bind existing OpenCode commands only in Vim normal mode:

{
  "plugin": [
    [
      "@leohenon/opencode-vim-plugin",
      {
        "vim_normal_leader": "space",
        "normal_keybinds": {
          "<leader>s": "session.list",
          "j": "session.line.down",
          "k": "session.line.up"
        }
      }
    ]
  ]
}

normal_keybinds values can be command strings or objects:

{
  "normal_keybinds": {
    "j": {
      "command": "session.line.down",
      "desc": "Scroll down",
      "preventDefault": false
    }
  }
}

Nested normal-mode keybind configuration is also accepted inside the plugin options:

{
  "plugin": [
    [
      "@leohenon/opencode-vim-plugin",
      {
        "keybinds": {
          "vim.normal": {
            "leader": "space",
            "session_list": "<leader>s",
            "messages_line_up": "<leader>k",
            "messages_line_down": "<leader>j"
          }
        }
      }
    ]
  ]
}

Submit behavior

By default, insert mode uses Enter for newlines and normal mode uses Enter to submit.

To submit from insert mode too:

{
  "plugin": [
    [
      "@leohenon/opencode-vim-plugin",
      {
        "vim_enter_submit": true
      }
    ]
  ]
}

To always default to insert mode after a prompt submission:

{
  "plugin": [
    [
      "@leohenon/opencode-vim-plugin",
      {
        "vim_insert_after_submit": true
      }
    ]
  ]
}

To keep newline available when vim_enter_submit is enabled, configure OpenCode's top-level input_newline keybind:

{
  "keybinds": {
    "input_newline": "alt+return"
  }
}

Or configure a separate OpenCode submit key:

{
  "keybinds": {
    "prompt_submit": "alt+return"
  }
}

input_newline and prompt_submit are OpenCode keybinds, not plugin options.

System clipboard register

Use the system clipboard as Vim's register:

{
  "plugin": [
    [
      "@leohenon/opencode-vim-plugin",
      {
        "vim_system_clipboard_register": true
      }
    ]
  ]
}

Yank and delete operations sync to the system clipboard, p / P paste from it.

Note

Clipboard sync uses pbcopy / pbpaste on macOS, PowerShell clipboard commands on Windows, and wl-copy / wl-paste, xclip, or xsel on Linux.

Vim langmap

Map non-English keyboard layout characters to Vim command keys.

Keys and values should be single characters.

{
  "plugin": [
    [
      "@leohenon/opencode-vim-plugin",
      {
        "vim_langmap": {
          "р": "h",
          "о": "j",
          "л": "k",
          "д": "l"
        }
      }
    ]
  ]
}

Or for simple aliases:

{
  "plugin": [
    [
      "@leohenon/opencode-vim-plugin",
      {
        "vim_langmap": {
          "H": "^",
          "L": "$"
        }
      }
    ]
  ]
}

Vim escape sequence

Set a two-character sequence to leave insert mode without pressing Escape:

{
  "plugin": [
    [
      "@leohenon/opencode-vim-plugin",
      {
        "vim_escape_sequence": "jk"
      }
    ]
  ]
}

Want more?

This plugin covers the prompt only. For Vim controls across the whole TUI — copy mode, session navigation — see OpenCode Vim, a fork of OpenCode that this plugin shares its Vim core with.

Local development

bun install
bun run check

Launch a local installed OpenCode test workspace:

./script/test-installed.sh