From d52cd613d539af6f852b02aab5dc05b92664ffdf Mon Sep 17 00:00:00 2001 From: "blink-so[bot]" <211532188+blink-so[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 12:15:18 +0000 Subject: [PATCH 1/3] feat: add ClaudeCodeDiffAccept and ClaudeCodeDiffDeny user commands - Add ClaudeCodeDiffAccept and ClaudeCodeDiffDeny user commands to init.lua - Implement accept_current_diff() and deny_current_diff() functions in diff.lua - Refactor keymaps to use new commands instead of inline functions - Store diff context in buffer variables for command access - Update README.md with new commands and customization examples - Maintain backward compatibility with existing da and dq keymaps Resolves issue #44 by allowing users to customize diff keymaps without conflicts Co-authored-by: ThomasK33 <2198487+ThomasK33@users.noreply.github.com> Signed-off-by: Thomas Kosiewski --- README.md | 14 ++++++++++ lua/claudecode/diff.lua | 62 +++++++++++++++++++++++++++++++---------- lua/claudecode/init.lua | 15 ++++++++++ 3 files changed, 76 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 3eceda0..e8a254e 100644 --- a/README.md +++ b/README.md @@ -88,6 +88,8 @@ That's it! For more configuration options, see [Advanced Setup](#advanced-setup) - `:ClaudeCodeSend` - Send current visual selection to Claude, or add files from tree explorer - `:ClaudeCodeTreeAdd` - Add selected file(s) from tree explorer to Claude context (also available via ClaudeCodeSend) - `:ClaudeCodeAdd [start-line] [end-line]` - Add a specific file or directory to Claude context by path with optional line range +- `:ClaudeCodeDiffAccept` - Accept the current diff changes (equivalent to `da`) +- `:ClaudeCodeDiffDeny` - Deny/reject the current diff changes (equivalent to `dq`) ### Toggle Behavior @@ -155,6 +157,18 @@ When you reject changes, the diff view closes and the original file remains unch 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. +### Customizing Diff Keymaps + +The default keymaps (`da` and `dq`) can be customized by remapping them to the underlying commands: + +```lua +-- Example: Use different keymaps for diff handling +vim.keymap.set('n', 'ya', 'ClaudeCodeDiffAccept', { desc = 'Accept diff' }) +vim.keymap.set('n', 'yn', 'ClaudeCodeDiffDeny', { desc = 'Deny diff' }) +``` + +The commands `ClaudeCodeDiffAccept` and `ClaudeCodeDiffDeny` work only in diff buffers created by the plugin and will show a warning if used elsewhere. + ### How It Works 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. diff --git a/lua/claudecode/diff.lua b/lua/claudecode/diff.lua index 90cf4c7..1f0cc1b 100644 --- a/lua/claudecode/diff.lua +++ b/lua/claudecode/diff.lua @@ -578,23 +578,16 @@ function M._create_diff_view_from_window(target_window, old_file_path, new_buffe vim.cmd("wincmd =") vim.api.nvim_set_current_win(new_win) - local keymap_opts = { buffer = new_buffer, silent = true } - - vim.keymap.set("n", "da", function() - M._resolve_diff_as_saved(tab_name, new_buffer) - end, keymap_opts) + -- Store diff context in buffer variables for user commands + vim.b[new_buffer].claudecode_diff_tab_name = tab_name + vim.b[new_buffer].claudecode_diff_new_win = new_win + vim.b[new_buffer].claudecode_diff_target_win = target_window - vim.keymap.set("n", "dq", function() - if vim.api.nvim_win_is_valid(new_win) then - vim.api.nvim_win_close(new_win, true) - end - if vim.api.nvim_win_is_valid(target_window) then - vim.api.nvim_set_current_win(target_window) - vim.cmd("diffoff") - end + local keymap_opts = { buffer = new_buffer, silent = true } - M._resolve_diff_as_rejected(tab_name) - end, keymap_opts) + -- Use the new user commands instead of inline functions + vim.keymap.set("n", "da", "ClaudeCodeDiffAccept", keymap_opts) + vim.keymap.set("n", "dq", "ClaudeCodeDiffDeny", keymap_opts) -- Return window information for later storage return { @@ -899,4 +892,43 @@ function M.reload_file_buffers_manual(file_path, original_cursor_pos) return reload_file_buffers(file_path, original_cursor_pos) end +--- Accept the current diff (user command version) +-- This function reads the diff context from buffer variables +function M.accept_current_diff() + local current_buffer = vim.api.nvim_get_current_buf() + local tab_name = vim.b[current_buffer].claudecode_diff_tab_name + + if not tab_name then + vim.notify("No active diff found in current buffer", vim.log.levels.WARN) + return + end + + M._resolve_diff_as_saved(tab_name, current_buffer) +end + +--- Deny/reject the current diff (user command version) +-- This function reads the diff context from buffer variables +function M.deny_current_diff() + local current_buffer = vim.api.nvim_get_current_buf() + local tab_name = vim.b[current_buffer].claudecode_diff_tab_name + local new_win = vim.b[current_buffer].claudecode_diff_new_win + local target_window = vim.b[current_buffer].claudecode_diff_target_win + + if not tab_name then + vim.notify("No active diff found in current buffer", vim.log.levels.WARN) + return + end + + -- Close windows and clean up (same logic as the original keymap) + if new_win and vim.api.nvim_win_is_valid(new_win) then + vim.api.nvim_win_close(new_win, true) + end + if target_window and vim.api.nvim_win_is_valid(target_window) then + vim.api.nvim_set_current_win(target_window) + vim.cmd("diffoff") + end + + M._resolve_diff_as_rejected(tab_name) +end + return M diff --git a/lua/claudecode/init.lua b/lua/claudecode/init.lua index 9547ef6..1e5ad34 100644 --- a/lua/claudecode/init.lua +++ b/lua/claudecode/init.lua @@ -880,6 +880,21 @@ function M._create_commands() "Terminal module not found. Terminal commands (ClaudeCode, ClaudeCodeOpen, ClaudeCodeClose) not registered." ) end + + -- Diff management commands + vim.api.nvim_create_user_command("ClaudeCodeDiffAccept", function() + local diff = require("claudecode.diff") + diff.accept_current_diff() + end, { + desc = "Accept the current diff changes", + }) + + vim.api.nvim_create_user_command("ClaudeCodeDiffDeny", function() + local diff = require("claudecode.diff") + diff.deny_current_diff() + end, { + desc = "Deny/reject the current diff changes", + }) end --- Get version information From 0c5aaeb380e7a00a22c841db537e4fcbce14e0fa Mon Sep 17 00:00:00 2001 From: "blink-so[bot]" <211532188+blink-so[bot]@users.noreply.github.com> Date: Tue, 17 Jun 2025 12:38:14 +0000 Subject: [PATCH 2/3] refactor: move diff keymaps to LazyVim spec configuration - Remove hardcoded keymaps from diff.lua - Add diff keymaps to LazyVim specs in README.md and dev-config.lua - Update documentation to reflect LazyVim spec configuration approach - Provide clear examples for customizing diff keymaps - Maintain backward compatibility with default da and dq This allows users to easily customize or disable diff keymaps by modifying their LazyVim plugin configuration instead of needing to override hardcoded keymaps. Co-authored-by: ThomasK33 <2198487+ThomasK33@users.noreply.github.com> Signed-off-by: Thomas Kosiewski --- README.md | 25 +++++++++++++++++++------ dev-config.lua | 4 ++++ lua/claudecode/diff.lua | 9 ++++----- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index e8a254e..c33f05c 100644 --- a/README.md +++ b/README.md @@ -61,6 +61,9 @@ Using [lazy.nvim](https://github.com/folke/lazy.nvim): desc = "Add file", ft = { "NvimTree", "neo-tree", "oil" }, }, + -- Diff management + { "da", "ClaudeCodeDiffAccept", desc = "Accept diff" }, + { "dq", "ClaudeCodeDiffDeny", desc = "Deny diff" }, }, } ``` @@ -139,7 +142,7 @@ When Claude proposes changes to your files, the plugin opens a native Neovim dif ### Accepting Changes - **`:w` (save)** - Accept the changes and apply them to your file -- **`da`** - Accept the changes using the dedicated keymap +- **`da`** - Accept the changes using the dedicated keymap (configured in LazyVim spec) 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. @@ -148,7 +151,7 @@ Both methods signal Claude Code to apply the changes to your file, after which t ### Rejecting Changes - **`:q` or `:close`** - Close the diff view to reject the changes -- **`dq`** - Reject changes using the dedicated keymap +- **`dq`** - Reject changes using the dedicated keymap (configured in LazyVim spec) - **`:bdelete` or `:bwipeout`** - Delete the diff buffer to reject changes When you reject changes, the diff view closes and the original file remains unchanged. @@ -159,12 +162,22 @@ You can also navigate to the Claude Code terminal window and accept or reject di ### Customizing Diff Keymaps -The default keymaps (`da` and `dq`) can be customized by remapping them to the underlying commands: +The diff keymaps are configured in the LazyVim spec and can be customized by modifying the `keys` table: ```lua --- Example: Use different keymaps for diff handling -vim.keymap.set('n', 'ya', 'ClaudeCodeDiffAccept', { desc = 'Accept diff' }) -vim.keymap.set('n', 'yn', 'ClaudeCodeDiffDeny', { desc = 'Deny diff' }) +{ + "coder/claudecode.nvim", + config = true, + keys = { + -- ... other keymaps ... + + -- Customize diff keymaps to avoid conflicts (e.g., with debugger) + { "ya", "ClaudeCodeDiffAccept", desc = "Accept diff" }, + { "yn", "ClaudeCodeDiffDeny", desc = "Deny diff" }, + + -- Or disable them entirely by omitting them from the keys table + }, +} ``` The commands `ClaudeCodeDiffAccept` and `ClaudeCodeDiffDeny` work only in diff buffers created by the plugin and will show a warning if used elsewhere. diff --git a/dev-config.lua b/dev-config.lua index 525e61e..66c20ec 100644 --- a/dev-config.lua +++ b/dev-config.lua @@ -31,6 +31,10 @@ return { { "ai", "ClaudeCodeStatus", desc = "Claude Status" }, { "aS", "ClaudeCodeStart", desc = "Start Claude Server" }, { "aQ", "ClaudeCodeStop", desc = "Stop Claude Server" }, + + -- Diff management (buffer-local, only active in diff buffers) + { "da", "ClaudeCodeDiffAccept", desc = "Accept diff" }, + { "dq", "ClaudeCodeDiffDeny", desc = "Deny diff" }, }, -- Development configuration - all options shown with defaults commented out diff --git a/lua/claudecode/diff.lua b/lua/claudecode/diff.lua index 1f0cc1b..94f5a56 100644 --- a/lua/claudecode/diff.lua +++ b/lua/claudecode/diff.lua @@ -583,11 +583,10 @@ function M._create_diff_view_from_window(target_window, old_file_path, new_buffe vim.b[new_buffer].claudecode_diff_new_win = new_win vim.b[new_buffer].claudecode_diff_target_win = target_window - local keymap_opts = { buffer = new_buffer, silent = true } - - -- Use the new user commands instead of inline functions - vim.keymap.set("n", "da", "ClaudeCodeDiffAccept", keymap_opts) - vim.keymap.set("n", "dq", "ClaudeCodeDiffDeny", keymap_opts) + -- Note: Keymaps for diff accept/deny are now configured in the LazyVim spec + -- Users can customize them by adding to their plugin configuration: + -- { "da", "ClaudeCodeDiffAccept", desc = "Accept diff", buffer = true } + -- { "dq", "ClaudeCodeDiffDeny", desc = "Deny diff", buffer = true } -- Return window information for later storage return { From 195be5e9a600705db304f998d2b2571243702d25 Mon Sep 17 00:00:00 2001 From: Thomas Kosiewski Date: Tue, 17 Jun 2025 18:26:53 +0200 Subject: [PATCH 3/3] fix: resolve test failures and complete diff keymap refactor Fixes #44 - test failures were caused by missing vim.b mock in test environment. Changes: - Add vim.b metatable mock to handle buffer-local variables in tests - Update dev config diff keymaps to avoid conflicts (aa/ad) - Remove outdated keymap comments from diff.lua - Fix minor formatting issues in README.md Tests now pass: 278 successes / 0 failures / 0 errors Change-Id: I3af59441d9940869e3ed0f7566a09892908bd16b Signed-off-by: Thomas Kosiewski --- README.md | 4 ++-- dev-config.lua | 4 ++-- lua/claudecode/diff.lua | 5 ----- tests/mocks/vim.lua | 19 +++++++++++++++++++ 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index c33f05c..6cbf0bd 100644 --- a/README.md +++ b/README.md @@ -170,11 +170,11 @@ The diff keymaps are configured in the LazyVim spec and can be customized by mod config = true, keys = { -- ... other keymaps ... - + -- Customize diff keymaps to avoid conflicts (e.g., with debugger) { "ya", "ClaudeCodeDiffAccept", desc = "Accept diff" }, { "yn", "ClaudeCodeDiffDeny", desc = "Deny diff" }, - + -- Or disable them entirely by omitting them from the keys table }, } diff --git a/dev-config.lua b/dev-config.lua index 66c20ec..5e6dde6 100644 --- a/dev-config.lua +++ b/dev-config.lua @@ -33,8 +33,8 @@ return { { "aQ", "ClaudeCodeStop", desc = "Stop Claude Server" }, -- Diff management (buffer-local, only active in diff buffers) - { "da", "ClaudeCodeDiffAccept", desc = "Accept diff" }, - { "dq", "ClaudeCodeDiffDeny", desc = "Deny diff" }, + { "aa", "ClaudeCodeDiffAccept", desc = "Accept diff" }, + { "ad", "ClaudeCodeDiffDeny", desc = "Deny diff" }, }, -- Development configuration - all options shown with defaults commented out diff --git a/lua/claudecode/diff.lua b/lua/claudecode/diff.lua index 94f5a56..852e8d8 100644 --- a/lua/claudecode/diff.lua +++ b/lua/claudecode/diff.lua @@ -583,11 +583,6 @@ function M._create_diff_view_from_window(target_window, old_file_path, new_buffe vim.b[new_buffer].claudecode_diff_new_win = new_win vim.b[new_buffer].claudecode_diff_target_win = target_window - -- Note: Keymaps for diff accept/deny are now configured in the LazyVim spec - -- Users can customize them by adding to their plugin configuration: - -- { "da", "ClaudeCodeDiffAccept", desc = "Accept diff", buffer = true } - -- { "dq", "ClaudeCodeDiffDeny", desc = "Deny diff", buffer = true } - -- Return window information for later storage return { new_window = new_win, diff --git a/tests/mocks/vim.lua b/tests/mocks/vim.lua index 7041997..39141c7 100644 --- a/tests/mocks/vim.lua +++ b/tests/mocks/vim.lua @@ -582,6 +582,25 @@ local vim = { end, }), + b = setmetatable({}, { + __index = function(_, bufnr) + -- Return buffer-local variables for the given buffer + if vim._buffers[bufnr] then + if not vim._buffers[bufnr].b_vars then + vim._buffers[bufnr].b_vars = {} + end + return vim._buffers[bufnr].b_vars + end + return {} + end, + __newindex = function(_, bufnr, vars) + -- Set buffer-local variables for the given buffer + if vim._buffers[bufnr] then + vim._buffers[bufnr].b_vars = vars + end + end, + }), + deepcopy = function(tbl) if type(tbl) ~= "table" then return tbl