Skip to content

Commit 288c9bf

Browse files
ThomasK33claude
andauthored
refactor(diff): rename diff_opts.layout "inline" to "unified" (#295)
## Summary Renames the `diff_opts.layout = "inline"` option (added in #195, queued for v0.4.0 via release-please #279) to **`"unified"`**, before it ships in a tagged release. Tracked in #293. [@wookayin pointed out](#195 (comment)) that the shipped `"inline"` mode isn't a true "inline" diff in the VS Code sense — it renders a unified diff in a separate `rightbelow vsplit` pane, not an in-place virtual-text overlay in the same window. Naming it `"inline"` now would force a breaking rename later, once we add the real in-place overlay (the mode that most deserves the name `"inline"`). Renaming is free now (not yet released) and a breaking change after #279 merges. ## What changed - **Config value** `"inline"` → `"unified"`: validation + error message (`config.lua`), the `ClaudeCodeDiffLayout` type alias (`types.lua`), all four dispatch sites (`diff.lua`), and the stored `layout` value (`diff_inline.lua`). - **User-facing buffer name**: `<file> (inline diff)` → `<file> (unified diff)`. - **Docs**: README layout enum + label; a `CHANGELOG.md` `[Unreleased]` entry for `layout = "unified"`. - **Tests**: the accept test now expects `"unified"`; a new test asserts the former `"inline"` is rejected. ## Decisions - **No deprecated alias.** `"inline"` was never in a tagged release, so there's no backward-compat obligation, and rejecting it cleanly reserves the name for the future in-place overlay (#294). The validation error names `'unified'`, so anyone tracking `main` is pointed at the new value. - **Internal names kept.** The `diff_inline.lua` module, its functions, the `claudecode_inline_diff` buffer variable, and the `ClaudeCodeInlineDiff*` highlight groups are unchanged — they describe the inline-*style* rendering, not the layout value (#293 noted the buffer var can stay). This keeps the diff small and low-risk. - **#279 changelog** regenerates from commits via Communique on the next push to `main`, so the v0.4.0 entry reflects "unified" automatically; I did not hand-edit the bot branch. ## Validation - `mise run all`: treefmt clean, luacheck **0/0**, **703/703** tests pass (baseline 702 + the new rejection test). - Headless Neovim smoke test: `layout = "unified"` accepted, `"inline"` rejected (error names `'unified'`), `"vertical"` still works. The true in-place overlay (the future `"inline"`) is tracked in #294. Refs #293, #195, #82 🤖 Generated with [Claude Code](https://claude.com/claude-code) Signed-off-by: Thomas Kosiewski <tk@coder.com> Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 5a04f8b commit 288c9bf

7 files changed

Lines changed: 47 additions & 20 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
- `: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))
99
- `: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))
1010
- `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))
11+
- `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))
1112

1213
### Bug Fixes
1314

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,8 +376,8 @@ For deep technical details, see [ARCHITECTURE.md](./ARCHITECTURE.md).
376376

377377
-- Diff Integration
378378
diff_opts = {
379-
layout = "vertical", -- "vertical" (default), "horizontal", or "inline"
380-
-- "inline": VS Code-style unified diff in a single buffer with deleted
379+
layout = "vertical", -- "vertical" (default), "horizontal", or "unified"
380+
-- "unified": VS Code-style unified diff in a single buffer with deleted
381381
-- (red/strikethrough) and added (green) lines interleaved. Requires
382382
-- Neovim >= 0.9.0. Highlight groups are customizable: ClaudeCodeInlineDiffAdd,
383383
-- ClaudeCodeInlineDiffDelete, ClaudeCodeInlineDiffAddSign, ClaudeCodeInlineDiffDeleteSign.

lua/claudecode/config.lua

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ function M.validate(config)
132132
assert(
133133
config.diff_opts.layout == "vertical"
134134
or config.diff_opts.layout == "horizontal"
135-
or config.diff_opts.layout == "inline",
136-
"diff_opts.layout must be 'vertical', 'horizontal', or 'inline'"
135+
or config.diff_opts.layout == "unified",
136+
"diff_opts.layout must be 'vertical', 'horizontal', or 'unified'"
137137
)
138138
end
139139
if config.diff_opts.open_in_new_tab ~= nil then

lua/claudecode/diff.lua

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -838,8 +838,8 @@ function M._resolve_diff_as_saved(tab_name, buffer_id)
838838
return
839839
end
840840

841-
-- Dispatch to inline diff handler
842-
if diff_data.layout == "inline" then
841+
-- Dispatch to unified diff handler
842+
if diff_data.layout == "unified" then
843843
local inline = require("claudecode.diff_inline")
844844
inline.resolve_inline_as_saved(tab_name, diff_data)
845845
return
@@ -932,8 +932,8 @@ function M._resolve_diff_as_rejected(tab_name)
932932
return
933933
end
934934

935-
-- Dispatch to inline diff handler
936-
if diff_data.layout == "inline" then
935+
-- Dispatch to unified diff handler
936+
if diff_data.layout == "unified" then
937937
local inline = require("claudecode.diff_inline")
938938
inline.resolve_inline_as_rejected(tab_name, diff_data)
939939
return
@@ -1166,8 +1166,8 @@ function M._cleanup_diff_state(tab_name, reason)
11661166
return
11671167
end
11681168

1169-
-- Dispatch to inline diff handler
1170-
if diff_data.layout == "inline" then
1169+
-- Dispatch to unified diff handler
1170+
if diff_data.layout == "unified" then
11711171
local inline = require("claudecode.diff_inline")
11721172
inline.cleanup_inline_diff(tab_name, diff_data)
11731173
active_diffs[tab_name] = nil
@@ -1315,8 +1315,8 @@ function M._setup_blocking_diff(params, resolution_callback)
13151315
end
13161316
end
13171317

1318-
-- Dispatch to inline diff if configured
1319-
if config and config.diff_opts and config.diff_opts.layout == "inline" then
1318+
-- Dispatch to unified diff if configured
1319+
if config and config.diff_opts and config.diff_opts.layout == "unified" then
13201320
local inline = require("claudecode.diff_inline")
13211321
inline.setup_inline_diff(params, resolution_callback, config)
13221322
return

lua/claudecode/diff_inline.lua

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ function M.setup_inline_diff(params, resolution_callback, config)
197197
error({ code = -32000, message = "Buffer creation failed", data = "Could not create inline diff buffer" })
198198
end
199199

200-
pcall(vim.api.nvim_buf_set_name, buf, tab_name .. " (inline diff)")
200+
pcall(vim.api.nvim_buf_set_name, buf, tab_name .. " (unified diff)")
201201
vim.api.nvim_buf_set_option(buf, "buftype", "acwrite")
202202
vim.api.nvim_buf_set_option(buf, "bufhidden", "wipe")
203203

@@ -330,7 +330,7 @@ function M.setup_inline_diff(params, resolution_callback, config)
330330
})
331331
end
332332

333-
-- Register state with layout = "inline"
333+
-- Register state with layout = "unified"
334334
diff._register_diff_state(tab_name, {
335335
old_file_path = params.old_file_path,
336336
new_file_path = params.new_file_path,
@@ -345,7 +345,7 @@ function M.setup_inline_diff(params, resolution_callback, config)
345345
status = "pending",
346346
resolution_callback = resolution_callback,
347347
result_content = nil,
348-
layout = "inline",
348+
layout = "unified",
349349
-- Track the originating MCP client so close_diffs_for_client can tear this
350350
-- diff down if that client disconnects (parity with the native path, #261).
351351
client_id = params.client_id,

lua/claudecode/types.lua

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
---@alias ClaudeCodeLogLevel "trace"|"debug"|"info"|"warn"|"error"
3232

3333
-- Diff layout type alias
34-
---@alias ClaudeCodeDiffLayout "vertical"|"horizontal"|"inline"
34+
---@alias ClaudeCodeDiffLayout "vertical"|"horizontal"|"unified"
3535

3636
-- Behavior when rejecting new-file diffs
3737
---@alias ClaudeCodeNewFileRejectBehavior "keep_empty"|"close_window"

tests/unit/diff_inline_spec.lua

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -327,7 +327,7 @@ describe("Inline diff module", function()
327327
end)
328328

329329
describe("config validation", function()
330-
it("should accept layout = 'inline'", function()
330+
it("should accept layout = 'unified'", function()
331331
package.loaded["claudecode.config"] = nil
332332
package.loaded["claudecode.terminal"] = nil
333333
-- Stub terminal module with defaults
@@ -347,8 +347,8 @@ describe("Inline diff module", function()
347347
ensure_visible = function() end,
348348
}
349349
local config = require("claudecode.config")
350-
local applied = config.apply({ diff_opts = { layout = "inline" } })
351-
assert.are.equal("inline", applied.diff_opts.layout)
350+
local applied = config.apply({ diff_opts = { layout = "unified" } })
351+
assert.are.equal("unified", applied.diff_opts.layout)
352352
end)
353353

354354
it("should reject invalid layout values", function()
@@ -374,7 +374,33 @@ describe("Inline diff module", function()
374374
config.apply({ diff_opts = { layout = "invalid" } })
375375
end)
376376
assert.is_false(success)
377-
assert_contains(tostring(err), "inline")
377+
assert_contains(tostring(err), "'unified'")
378+
end)
379+
380+
it("should reject the former layout = 'inline' (renamed to 'unified')", function()
381+
package.loaded["claudecode.config"] = nil
382+
package.loaded["claudecode.terminal"] = nil
383+
package.loaded["claudecode.terminal"] = {
384+
defaults = {
385+
split_side = "right",
386+
split_width_percentage = 0.30,
387+
provider = "auto",
388+
show_native_term_exit_tip = true,
389+
auto_close = true,
390+
env = {},
391+
snacks_win_opts = {},
392+
},
393+
get_active_terminal_bufnr = function()
394+
return nil
395+
end,
396+
ensure_visible = function() end,
397+
}
398+
local config = require("claudecode.config")
399+
local success, err = pcall(function()
400+
config.apply({ diff_opts = { layout = "inline" } })
401+
end)
402+
assert.is_false(success)
403+
assert_contains(tostring(err), "'unified'")
378404
end)
379405
end)
380406

0 commit comments

Comments
 (0)