Skip to content

Commit d836f76

Browse files
feat: make diff keymaps adjustable via LazyVim spec (#47)
Co-authored-by: ThomasK33 <2198487+ThomasK33@users.noreply.github.com> Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
1 parent 030fa7c commit d836f76

File tree

5 files changed

+110
-19
lines changed

5 files changed

+110
-19
lines changed

README.md

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ Using [lazy.nvim](https://github.com/folke/lazy.nvim):
6161
desc = "Add file",
6262
ft = { "NvimTree", "neo-tree", "oil" },
6363
},
64+
-- Diff management
65+
{ "<leader>da", "<cmd>ClaudeCodeDiffAccept<cr>", desc = "Accept diff" },
66+
{ "<leader>dq", "<cmd>ClaudeCodeDiffDeny<cr>", desc = "Deny diff" },
6467
},
6568
}
6669
```
@@ -88,6 +91,8 @@ That's it! For more configuration options, see [Advanced Setup](#advanced-setup)
8891
- `:ClaudeCodeSend` - Send current visual selection to Claude, or add files from tree explorer
8992
- `:ClaudeCodeTreeAdd` - Add selected file(s) from tree explorer to Claude context (also available via ClaudeCodeSend)
9093
- `:ClaudeCodeAdd <file-path> [start-line] [end-line]` - Add a specific file or directory to Claude context by path with optional line range
94+
- `:ClaudeCodeDiffAccept` - Accept the current diff changes (equivalent to `<leader>da`)
95+
- `:ClaudeCodeDiffDeny` - Deny/reject the current diff changes (equivalent to `<leader>dq`)
9196

9297
### Toggle Behavior
9398

@@ -137,7 +142,7 @@ When Claude proposes changes to your files, the plugin opens a native Neovim dif
137142
### Accepting Changes
138143

139144
- **`:w` (save)** - Accept the changes and apply them to your file
140-
- **`<leader>da`** - Accept the changes using the dedicated keymap
145+
- **`<leader>da`** - Accept the changes using the dedicated keymap (configured in LazyVim spec)
141146

142147
You can edit the proposed changes in the right-hand diff buffer before accepting them. This allows you to modify Claude's suggestions or make additional tweaks before applying the final version to your file.
143148

@@ -146,7 +151,7 @@ Both methods signal Claude Code to apply the changes to your file, after which t
146151
### Rejecting Changes
147152

148153
- **`:q` or `:close`** - Close the diff view to reject the changes
149-
- **`<leader>dq`** - Reject changes using the dedicated keymap
154+
- **`<leader>dq`** - Reject changes using the dedicated keymap (configured in LazyVim spec)
150155
- **`:bdelete` or `:bwipeout`** - Delete the diff buffer to reject changes
151156

152157
When you reject changes, the diff view closes and the original file remains unchanged.
@@ -155,6 +160,28 @@ When you reject changes, the diff view closes and the original file remains unch
155160

156161
You can also navigate to the Claude Code terminal window and accept or reject diffs directly from within Claude's interface. This provides an alternative way to manage diffs without using the Neovim-specific keymaps.
157162

163+
### Customizing Diff Keymaps
164+
165+
The diff keymaps are configured in the LazyVim spec and can be customized by modifying the `keys` table:
166+
167+
```lua
168+
{
169+
"coder/claudecode.nvim",
170+
config = true,
171+
keys = {
172+
-- ... other keymaps ...
173+
174+
-- Customize diff keymaps to avoid conflicts (e.g., with debugger)
175+
{ "<leader>ya", "<cmd>ClaudeCodeDiffAccept<cr>", desc = "Accept diff" },
176+
{ "<leader>yn", "<cmd>ClaudeCodeDiffDeny<cr>", desc = "Deny diff" },
177+
178+
-- Or disable them entirely by omitting them from the keys table
179+
},
180+
}
181+
```
182+
183+
The commands `ClaudeCodeDiffAccept` and `ClaudeCodeDiffDeny` work only in diff buffers created by the plugin and will show a warning if used elsewhere.
184+
158185
### How It Works
159186

160187
The plugin uses a signal-based approach where accepting or rejecting a diff sends a message to Claude Code rather than directly modifying files. This ensures consistency and allows Claude Code to handle the actual file operations while the plugin manages the user interface and buffer reloading.

dev-config.lua

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ return {
3131
{ "<leader>ai", "<cmd>ClaudeCodeStatus<cr>", desc = "Claude Status" },
3232
{ "<leader>aS", "<cmd>ClaudeCodeStart<cr>", desc = "Start Claude Server" },
3333
{ "<leader>aQ", "<cmd>ClaudeCodeStop<cr>", desc = "Stop Claude Server" },
34+
35+
-- Diff management (buffer-local, only active in diff buffers)
36+
{ "<leader>aa", "<cmd>ClaudeCodeDiffAccept<cr>", desc = "Accept diff" },
37+
{ "<leader>ad", "<cmd>ClaudeCodeDiffDeny<cr>", desc = "Deny diff" },
3438
},
3539

3640
-- Development configuration - all options shown with defaults commented out

lua/claudecode/diff.lua

Lines changed: 43 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -578,23 +578,10 @@ function M._create_diff_view_from_window(target_window, old_file_path, new_buffe
578578
vim.cmd("wincmd =")
579579
vim.api.nvim_set_current_win(new_win)
580580

581-
local keymap_opts = { buffer = new_buffer, silent = true }
582-
583-
vim.keymap.set("n", "<leader>da", function()
584-
M._resolve_diff_as_saved(tab_name, new_buffer)
585-
end, keymap_opts)
586-
587-
vim.keymap.set("n", "<leader>dq", function()
588-
if vim.api.nvim_win_is_valid(new_win) then
589-
vim.api.nvim_win_close(new_win, true)
590-
end
591-
if vim.api.nvim_win_is_valid(target_window) then
592-
vim.api.nvim_set_current_win(target_window)
593-
vim.cmd("diffoff")
594-
end
595-
596-
M._resolve_diff_as_rejected(tab_name)
597-
end, keymap_opts)
581+
-- Store diff context in buffer variables for user commands
582+
vim.b[new_buffer].claudecode_diff_tab_name = tab_name
583+
vim.b[new_buffer].claudecode_diff_new_win = new_win
584+
vim.b[new_buffer].claudecode_diff_target_win = target_window
598585

599586
-- Return window information for later storage
600587
return {
@@ -899,4 +886,43 @@ function M.reload_file_buffers_manual(file_path, original_cursor_pos)
899886
return reload_file_buffers(file_path, original_cursor_pos)
900887
end
901888

889+
--- Accept the current diff (user command version)
890+
-- This function reads the diff context from buffer variables
891+
function M.accept_current_diff()
892+
local current_buffer = vim.api.nvim_get_current_buf()
893+
local tab_name = vim.b[current_buffer].claudecode_diff_tab_name
894+
895+
if not tab_name then
896+
vim.notify("No active diff found in current buffer", vim.log.levels.WARN)
897+
return
898+
end
899+
900+
M._resolve_diff_as_saved(tab_name, current_buffer)
901+
end
902+
903+
--- Deny/reject the current diff (user command version)
904+
-- This function reads the diff context from buffer variables
905+
function M.deny_current_diff()
906+
local current_buffer = vim.api.nvim_get_current_buf()
907+
local tab_name = vim.b[current_buffer].claudecode_diff_tab_name
908+
local new_win = vim.b[current_buffer].claudecode_diff_new_win
909+
local target_window = vim.b[current_buffer].claudecode_diff_target_win
910+
911+
if not tab_name then
912+
vim.notify("No active diff found in current buffer", vim.log.levels.WARN)
913+
return
914+
end
915+
916+
-- Close windows and clean up (same logic as the original keymap)
917+
if new_win and vim.api.nvim_win_is_valid(new_win) then
918+
vim.api.nvim_win_close(new_win, true)
919+
end
920+
if target_window and vim.api.nvim_win_is_valid(target_window) then
921+
vim.api.nvim_set_current_win(target_window)
922+
vim.cmd("diffoff")
923+
end
924+
925+
M._resolve_diff_as_rejected(tab_name)
926+
end
927+
902928
return M

lua/claudecode/init.lua

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -880,6 +880,21 @@ function M._create_commands()
880880
"Terminal module not found. Terminal commands (ClaudeCode, ClaudeCodeOpen, ClaudeCodeClose) not registered."
881881
)
882882
end
883+
884+
-- Diff management commands
885+
vim.api.nvim_create_user_command("ClaudeCodeDiffAccept", function()
886+
local diff = require("claudecode.diff")
887+
diff.accept_current_diff()
888+
end, {
889+
desc = "Accept the current diff changes",
890+
})
891+
892+
vim.api.nvim_create_user_command("ClaudeCodeDiffDeny", function()
893+
local diff = require("claudecode.diff")
894+
diff.deny_current_diff()
895+
end, {
896+
desc = "Deny/reject the current diff changes",
897+
})
883898
end
884899

885900
--- Get version information

tests/mocks/vim.lua

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,25 @@ local vim = {
582582
end,
583583
}),
584584

585+
b = setmetatable({}, {
586+
__index = function(_, bufnr)
587+
-- Return buffer-local variables for the given buffer
588+
if vim._buffers[bufnr] then
589+
if not vim._buffers[bufnr].b_vars then
590+
vim._buffers[bufnr].b_vars = {}
591+
end
592+
return vim._buffers[bufnr].b_vars
593+
end
594+
return {}
595+
end,
596+
__newindex = function(_, bufnr, vars)
597+
-- Set buffer-local variables for the given buffer
598+
if vim._buffers[bufnr] then
599+
vim._buffers[bufnr].b_vars = vars
600+
end
601+
end,
602+
}),
603+
585604
deepcopy = function(tbl)
586605
if type(tbl) ~= "table" then
587606
return tbl

0 commit comments

Comments
 (0)