Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@ node_modules/
.opencode/
docs/*
!docs/configuration.md
!docs/configuration.zh.md
assets/*.mp4
assets/screenshot-*.png
22 changes: 12 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,17 @@ opencode plugin opencode-vim@latest --global

## Supported Keys

| Key | Behavior |
| --- | --- |
| `<Esc>`, `<C-[>` | Enter normal mode |
| `i`, `a`, `A`, `o`, `O` | Return to insert mode |
| `h`, `j`, `k`, `l`, `w`, `b`, `e`, `$`, `0` | Move through the prompt |
| `x`, `d`, `c`, `y`, `p`, `u`, `<C-r>` | Edit, yank, paste, undo, redo |
| `v`, `V` | Visual and visual-line selection |
| `3w`, `diw`, `ci"`, `yiq`, `dip`, `yib` | Counts and text objects |
| `<CR>` in normal mode | Submit the prompt |
| `/vim` | Toggle Vim mode on or off |
| Key | Behavior |
| ------------------------------------------- | -------------------------------------------- |
| `<Esc>`, `<C-[>` | Enter normal mode |
| `i`, `a`, `A`, `o`, `O` | Return to insert mode |
| `h`, `j`, `k`, `l`, `w`, `b`, `e`, `$`, `0` | Move through the prompt |
| `x`, `d`, `c`, `y`, `p`, `u`, `<C-r>` | Edit, yank, paste, undo, redo |
| `v`, `V` | Visual and visual-line selection |
| `3w`, `diw`, `ci"`, `yiq`, `dip`, `yib` | Counts and text objects |
| `<CR>` in normal mode | Submit (default). Configurable via `keymaps` |
| `/vim` | Toggle Vim mode on or off |

See [docs/configuration.md](./docs/configuration.md) for configuration options and keymap examples.

中文文档:[README.zh.md](./README.zh.md) | [docs/configuration.zh.md](./docs/configuration.zh.md)
28 changes: 28 additions & 0 deletions README.zh.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# opencode-vim

为 OpenCode 输入框添加 Vim 风格的 insert 和 normal 模式编辑。

![Demo](./assets/demo2.gif)

## 安装

通过命令行安装:

```bash
opencode plugin opencode-vim@latest --global
```

## 快捷键

| 按键 | 说明 |
| ------------------------------------------- | ---------------------------------------- |
| `<Esc>`, `<C-[>` | 进入 normal 模式 |
| `i`, `a`, `A`, `o`, `O` | 返回 insert 模式 |
| `h`, `j`, `k`, `l`, `w`, `b`, `e`, `$`, `0` | 移动光标 |
| `x`, `d`, `c`, `y`, `p`, `u`, `<C-r>` | 编辑、复制、粘贴、撤销、重做 |
| `v`, `V` | 可视模式和可视行模式 |
| `3w`, `diw`, `ci"`, `yiq`, `dip`, `yib` | 计数和文本对象 |
| normal 模式下 `<CR>` | 提交 prompt(默认,可通过 keymaps 配置) |
| `/vim` | 开关 Vim 模式 |

配置文档:[docs/configuration.zh.md](./docs/configuration.zh.md)
109 changes: 58 additions & 51 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ Add `opencode-vim` to the `plugin` array in your OpenCode `tui.jsonc` file:

```jsonc
{
"$schema": "https://opencode.ai/tui.json",
"plugin": [
[
"./plugin/opencode-vim",
{
"autoUpdate": true,
"vim": {
"defaultMode": "insert"
}
}
]
]
"$schema": "https://opencode.ai/tui.json",
"plugin": [
[
"./plugin/opencode-vim",
{
"autoUpdate": true,
"vim": {
"defaultMode": "insert",
},
},
],
],
}
```

Expand All @@ -29,41 +29,41 @@ If your plugin is installed somewhere else, change the plugin path to match your

```jsonc
{
"$schema": "https://opencode.ai/tui.json",
"plugin": [
[
"./plugin/opencode-vim",
{
"autoUpdate": true,
"vim": {
"defaultMode": "insert",
"keymapTimeout": 500,
"pendingDisplayDelay": 120,
"cursorStyles": {
"insert": {
"style": "line",
"blinking": true
},
"normal": {
"style": "block",
"blinking": true
}
},
"debug": false,
"debugPath": "/home/you/.cache/opencode/opencode-vim.log",
"keymaps": {
"insert": {
"kj": "normal"
"$schema": "https://opencode.ai/tui.json",
"plugin": [
[
"./plugin/opencode-vim",
{
"autoUpdate": true,
"vim": {
"defaultMode": "insert",
"keymapTimeout": 500,
"pendingDisplayDelay": 120,
"cursorStyles": {
"insert": {
"style": "line",
"blinking": true,
},
"normal": {
"style": "block",
"blinking": true,
},
},
"debug": false,
"debugPath": "/home/you/.cache/opencode/opencode-vim.log",
"keymaps": {
"insert": {
"kj": "normal",
},
"normal": {
"<CR>": "submit",
"Y": "y$",
},
},
},
},
"normal": {
"<CR>": "submit",
"Y": "y$"
}
}
}
}
]
]
],
],
}
```

Expand Down Expand Up @@ -268,11 +268,14 @@ Each keymap entry maps a key sequence to an action:

Supported built-in actions:

- `"normal"` exits insert mode and enters normal mode.
- `"insert"` enters insert mode.
- `"submit"` submits the OpenCode prompt.
| Action | Modes | Effect |
|---|---|---|
| `"submit"` | insert, normal | Submits the prompt |
| `"normal"` | insert only | Exits insert mode, enters normal mode |
| `"insert"` | normal only | Enters insert mode |
| `"<vim keys>"` | normal only | Executes the configured Vim key sequence |

Any other action string is treated as a Vim key sequence. For example, this maps `Y` to yank from the cursor to the end of the line:
For example, this maps `Y` to yank from the cursor to the end of the line:

```jsonc
"keymaps": {
Expand All @@ -282,6 +285,10 @@ Any other action string is treated as a Vim key sequence. For example, this maps
}
```

Unlike other keys, `<CR>` in normal mode defaults to `"submit"` when no mapping is configured. In insert mode, if `<CR>` is unmapped and OpenCode's `input_submit` is not `return`, it inserts a newline instead of submitting.

> **Note:** When `input_submit` is not `"return"`, make sure to also set `"input_newline": "return"` in the OpenCode `keybinds` config. Without it, `<CR>` in insert mode does nothing (neither submits nor inserts a newline).

## Keymap Syntax

Key sequences can contain printable ASCII characters, except literal spaces. Use `<Space>` for the space key.
Expand Down Expand Up @@ -331,7 +338,7 @@ Use `kj` or `jk` to leave insert mode:
}
```

Submit the prompt with Enter in normal mode:
Submit with `<CR>` in normal mode is the default — this keymap is optional:

```jsonc
"keymaps": {
Expand Down
Loading