diff --git a/README.md b/README.md index 95921586..39ed33ac 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ Integrate the [opencode](https://github.com/sst/opencode) AI assistant with Neov vim.keymap.set({ "n", "x" }, "go", function() return require("opencode").operator("@this ") end, { desc = "Add range to opencode", expr = true }) vim.keymap.set("n", "goo", function() return require("opencode").operator("@this ") .. "_" end, { desc = "Add line to opencode", expr = true }) + -- The default / keymaps will work in the normal mode but it is possible to scroll opencode from any buffer: vim.keymap.set("n", "", function() require("opencode").command("session.half.page.up") end, { desc = "Scroll opencode up" }) vim.keymap.set("n", "", function() require("opencode").command("session.half.page.down") end, { desc = "Scroll opencode down" }) @@ -79,17 +80,17 @@ programs.nixvim = { `opencode.nvim` replaces placeholders in prompts with the corresponding context: -| Placeholder | Context | -| -------------- | ------------------------------------------------------------- | -| `@this` | Operator range or visual selection if any, else cursor position | -| `@buffer` | Current buffer | -| `@buffers` | Open buffers | -| `@visible` | Visible text | -| `@diagnostics` | Current buffer diagnostics | -| `@quickfix` | Quickfix list | -| `@diff` | Git diff | -| `@marks` | Global marks | -| `@grapple` | [grapple.nvim](https://github.com/cbochs/grapple.nvim) tags | +| Placeholder | Context | +| -------------- | --------------------------------------------------------------- | +| `@this` | Operator range or visual selection if any, else cursor position | +| `@buffer` | Current buffer | +| `@buffers` | Open buffers | +| `@visible` | Visible text | +| `@diagnostics` | Current buffer diagnostics | +| `@quickfix` | Quickfix list | +| `@diff` | Git diff | +| `@marks` | Global marks | +| `@grapple` | [grapple.nvim](https://github.com/cbochs/grapple.nvim) tags | ### Prompts @@ -107,6 +108,37 @@ Select or reference prompts to review, explain, and improve your code: | `review` | Review `@this` for correctness and readability | | `test` | Add tests for `@this` | +### Keymaps + +`opencode.nvim` sets these buffer-local keymaps in opencode terminal buffers by default: + +| Keymap | Command | Description | +| ------- | ------------------------ | ---------------------------- | +| `` | `session.half.page.up` | Scroll up half page | +| `` | `session.half.page.down` | Scroll down half page | +| `` | `session.interrupt` | Interrup (same as esc press) | +| `gg` | `session.first` | Go to first message | +| `G` | `session.last` | Go to last message | + +You can customize or disable these keymaps: + +```lua +vim.g.opencode_opts = { + -- Customize keymaps + keymaps = { + n = { + [""] = { "session.half.page.up", desc = "Scroll up" }, + [""] = { "session.half.page.down", desc = "Scroll down" }, + ["gg"] = false, -- Disable this keymap + -- Add custom keymaps + [""] = { "session.new", desc = "New session" }, + }, + }, + -- Or disable all default keymaps + -- keymaps = false, +} +``` + ### Provider You can manually run `opencode` inside Neovim's CWD however you like and `opencode.nvim` will find it! diff --git a/lua/opencode/keymaps.lua b/lua/opencode/keymaps.lua new file mode 100644 index 00000000..e3971528 --- /dev/null +++ b/lua/opencode/keymaps.lua @@ -0,0 +1,29 @@ +local M = {} + +---Apply buffer-local keymaps to the given buffer. +---@param bufnr integer The buffer number to apply keymaps to. +function M.apply(bufnr) + local opts = { buffer = bufnr } + + vim.keymap.set("n", "", function() + require("opencode.api.command").command("session.half.page.up") + end, vim.tbl_extend("force", opts, { desc = "Scroll up half page" })) + + vim.keymap.set("n", "", function() + require("opencode.api.command").command("session.half.page.down") + end, vim.tbl_extend("force", opts, { desc = "Scroll down half page" })) + + vim.keymap.set("n", "gg", function() + require("opencode.api.command").command("session.first") + end, vim.tbl_extend("force", opts, { desc = "Go to first message" })) + + vim.keymap.set("n", "G", function() + require("opencode.api.command").command("session.last") + end, vim.tbl_extend("force", opts, { desc = "Go to last message" })) + + vim.keymap.set("n", "", function() + require("opencode.api.command").command("session.interrupt") + end, vim.tbl_extend("force", opts, { desc = "Interrupt current session (esc)" })) +end + +return M diff --git a/lua/opencode/provider/snacks.lua b/lua/opencode/provider/snacks.lua index af356a52..f8ab8e66 100644 --- a/lua/opencode/provider/snacks.lua +++ b/lua/opencode/provider/snacks.lua @@ -25,7 +25,7 @@ function Snacks.health() return "`snacks.nvim` is not available.", { "Install `snacks.nvim` and enable `snacks.terminal.`", } - elseif not snacks.config.get("terminal", {}).enabled then + elseif not snacks and snacks.config.get("terminal", {}).enabled then return "`snacks.terminal` is not enabled.", { "Enable `snacks.terminal` in your `snacks.nvim` configuration.", diff --git a/lua/opencode/provider/terminal.lua b/lua/opencode/provider/terminal.lua index dab7acdd..f0a0809b 100644 --- a/lua/opencode/provider/terminal.lua +++ b/lua/opencode/provider/terminal.lua @@ -49,6 +49,8 @@ function Terminal:start() self.bufnr = vim.api.nvim_create_buf(true, false) self.winid = vim.api.nvim_open_win(self.bufnr, true, self.opts) + require("opencode.keymaps").apply(self.bufnr) + -- Redraw terminal buffer on initial render. -- Fixes empty columns on the right side. local auid diff --git a/plugin/keymaps.lua b/plugin/keymaps.lua new file mode 100644 index 00000000..d5b551a4 --- /dev/null +++ b/plugin/keymaps.lua @@ -0,0 +1,8 @@ +-- Apply buffer-local keymaps to opencode terminal buffers. +-- This handles the snacks provider (and any other provider using `opencode_terminal` filetype). +vim.api.nvim_create_autocmd("FileType", { + pattern = "opencode_terminal", + callback = function(ev) + require("opencode.keymaps").apply(ev.buf) + end, +})