Skip to content
Merged
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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
- `:ClaudeCodeCloseAllDiffs` command to close pending Claude diffs at once (e.g. proposals orphaned by resolving them via Claude remote control). Diffs you have already accepted but whose file has not been written yet are left intact so saved edits are never discarded. ([#248](https://github.com/coder/claudecode.nvim/issues/248))
- `:ClaudeCodeSendText {text}` command (and `require("claudecode.terminal").send_to_terminal(text, opts)` function) to send arbitrary text to the open Claude terminal as if typed at the prompt, submitting it by default. `:ClaudeCodeSendText!` inserts the text without submitting. Handy for scripting and keymaps; multi-line text is sent via bracketed paste. Works with the in-editor `native`/`snacks` providers only — `external`/`none` run Claude outside Neovim, where there is no pane to write to. ([#197](https://github.com/coder/claudecode.nvim/issues/197))
- `terminal.auto_insert` option (default `true`) controlling whether the Claude terminal auto-enters insert/terminal mode when its window gains focus. With the default Snacks provider, switching back into the terminal window (e.g. `<C-w>l`) previously re-entered terminal mode and jumped to the bottom prompt, discarding your Normal-mode scroll/reading position; set `auto_insert = false` to stay in Normal mode and preserve the scroll position (press `i` to type). Applies to the `native` and `snacks` providers and the new-tab diff terminal. ([#232](https://github.com/coder/claudecode.nvim/issues/232), [#145](https://github.com/coder/claudecode.nvim/issues/145))
- `diff_opts.layout = "unified"`: a unified diff rendered in a single buffer with deleted (red/strikethrough) and added (green) lines interleaved, as a compact alternative to the two-pane `"vertical"`/`"horizontal"` layouts. Requires Neovim >= 0.9.0; the `ClaudeCodeInlineDiffAdd`/`Delete`/`AddSign`/`DeleteSign` highlight groups are customizable. ([#82](https://github.com/coder/claudecode.nvim/issues/82), [#195](https://github.com/coder/claudecode.nvim/pull/195), [#293](https://github.com/coder/claudecode.nvim/issues/293))

### Bug Fixes

Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,8 @@ For deep technical details, see [ARCHITECTURE.md](./ARCHITECTURE.md).

-- Diff Integration
diff_opts = {
layout = "vertical", -- "vertical" (default), "horizontal", or "inline"
-- "inline": VS Code-style unified diff in a single buffer with deleted
layout = "vertical", -- "vertical" (default), "horizontal", or "unified"
-- "unified": VS Code-style unified diff in a single buffer with deleted
-- (red/strikethrough) and added (green) lines interleaved. Requires
-- Neovim >= 0.9.0. Highlight groups are customizable: ClaudeCodeInlineDiffAdd,
-- ClaudeCodeInlineDiffDelete, ClaudeCodeInlineDiffAddSign, ClaudeCodeInlineDiffDeleteSign.
Expand Down
4 changes: 2 additions & 2 deletions lua/claudecode/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,8 @@ function M.validate(config)
assert(
config.diff_opts.layout == "vertical"
or config.diff_opts.layout == "horizontal"
or config.diff_opts.layout == "inline",
"diff_opts.layout must be 'vertical', 'horizontal', or 'inline'"
or config.diff_opts.layout == "unified",
"diff_opts.layout must be 'vertical', 'horizontal', or 'unified'"
)
end
if config.diff_opts.open_in_new_tab ~= nil then
Expand Down
16 changes: 8 additions & 8 deletions lua/claudecode/diff.lua
Original file line number Diff line number Diff line change
Expand Up @@ -838,8 +838,8 @@ function M._resolve_diff_as_saved(tab_name, buffer_id)
return
end

-- Dispatch to inline diff handler
if diff_data.layout == "inline" then
-- Dispatch to unified diff handler
if diff_data.layout == "unified" then
local inline = require("claudecode.diff_inline")
inline.resolve_inline_as_saved(tab_name, diff_data)
return
Expand Down Expand Up @@ -932,8 +932,8 @@ function M._resolve_diff_as_rejected(tab_name)
return
end

-- Dispatch to inline diff handler
if diff_data.layout == "inline" then
-- Dispatch to unified diff handler
if diff_data.layout == "unified" then
local inline = require("claudecode.diff_inline")
inline.resolve_inline_as_rejected(tab_name, diff_data)
return
Expand Down Expand Up @@ -1166,8 +1166,8 @@ function M._cleanup_diff_state(tab_name, reason)
return
end

-- Dispatch to inline diff handler
if diff_data.layout == "inline" then
-- Dispatch to unified diff handler
if diff_data.layout == "unified" then
local inline = require("claudecode.diff_inline")
inline.cleanup_inline_diff(tab_name, diff_data)
active_diffs[tab_name] = nil
Expand Down Expand Up @@ -1315,8 +1315,8 @@ function M._setup_blocking_diff(params, resolution_callback)
end
end

-- Dispatch to inline diff if configured
if config and config.diff_opts and config.diff_opts.layout == "inline" then
-- Dispatch to unified diff if configured
if config and config.diff_opts and config.diff_opts.layout == "unified" then
local inline = require("claudecode.diff_inline")
inline.setup_inline_diff(params, resolution_callback, config)
return
Expand Down
6 changes: 3 additions & 3 deletions lua/claudecode/diff_inline.lua
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ function M.setup_inline_diff(params, resolution_callback, config)
error({ code = -32000, message = "Buffer creation failed", data = "Could not create inline diff buffer" })
end

pcall(vim.api.nvim_buf_set_name, buf, tab_name .. " (inline diff)")
pcall(vim.api.nvim_buf_set_name, buf, tab_name .. " (unified diff)")
vim.api.nvim_buf_set_option(buf, "buftype", "acwrite")
vim.api.nvim_buf_set_option(buf, "bufhidden", "wipe")

Expand Down Expand Up @@ -330,7 +330,7 @@ function M.setup_inline_diff(params, resolution_callback, config)
})
end

-- Register state with layout = "inline"
-- Register state with layout = "unified"
diff._register_diff_state(tab_name, {
old_file_path = params.old_file_path,
new_file_path = params.new_file_path,
Expand All @@ -345,7 +345,7 @@ function M.setup_inline_diff(params, resolution_callback, config)
status = "pending",
resolution_callback = resolution_callback,
result_content = nil,
layout = "inline",
layout = "unified",
-- Track the originating MCP client so close_diffs_for_client can tear this
-- diff down if that client disconnects (parity with the native path, #261).
client_id = params.client_id,
Expand Down
2 changes: 1 addition & 1 deletion lua/claudecode/types.lua
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
---@alias ClaudeCodeLogLevel "trace"|"debug"|"info"|"warn"|"error"

-- Diff layout type alias
---@alias ClaudeCodeDiffLayout "vertical"|"horizontal"|"inline"
---@alias ClaudeCodeDiffLayout "vertical"|"horizontal"|"unified"

-- Behavior when rejecting new-file diffs
---@alias ClaudeCodeNewFileRejectBehavior "keep_empty"|"close_window"
Expand Down
34 changes: 30 additions & 4 deletions tests/unit/diff_inline_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,7 @@ describe("Inline diff module", function()
end)

describe("config validation", function()
it("should accept layout = 'inline'", function()
it("should accept layout = 'unified'", function()
package.loaded["claudecode.config"] = nil
package.loaded["claudecode.terminal"] = nil
-- Stub terminal module with defaults
Expand All @@ -347,8 +347,8 @@ describe("Inline diff module", function()
ensure_visible = function() end,
}
local config = require("claudecode.config")
local applied = config.apply({ diff_opts = { layout = "inline" } })
assert.are.equal("inline", applied.diff_opts.layout)
local applied = config.apply({ diff_opts = { layout = "unified" } })
assert.are.equal("unified", applied.diff_opts.layout)
end)

it("should reject invalid layout values", function()
Expand All @@ -374,7 +374,33 @@ describe("Inline diff module", function()
config.apply({ diff_opts = { layout = "invalid" } })
end)
assert.is_false(success)
assert_contains(tostring(err), "inline")
assert_contains(tostring(err), "'unified'")
end)

it("should reject the former layout = 'inline' (renamed to 'unified')", function()
package.loaded["claudecode.config"] = nil
package.loaded["claudecode.terminal"] = nil
package.loaded["claudecode.terminal"] = {
defaults = {
split_side = "right",
split_width_percentage = 0.30,
provider = "auto",
show_native_term_exit_tip = true,
auto_close = true,
env = {},
snacks_win_opts = {},
},
get_active_terminal_bufnr = function()
return nil
end,
ensure_visible = function() end,
}
local config = require("claudecode.config")
local success, err = pcall(function()
config.apply({ diff_opts = { layout = "inline" } })
end)
assert.is_false(success)
assert_contains(tostring(err), "'unified'")
end)
end)

Expand Down
Loading