fix(diff): reuse tabnew window for unified new-tab diff#303
Open
zakissimo wants to merge 1 commit into
Open
Conversation
The unified (inline) diff opened in a new tab left an empty [No Name]
pane and could leak its tab. Two issues in setup_inline_diff, both hit by
layout = "unified" + open_in_new_tab = true:
1. The diff was opened with `rightbelow vsplit` off the ephemeral window
created by `:tabnew`, so that empty [No Name] window lingered beside
the diff and `wincmd =` split the width evenly. Reuse the ephemeral
window as the diff window instead. The in-current-tab path keeps the
split so it does not replace the user's buffer.
2. guard_inline_setup captured display_terminal_in_new_tab()'s return
values with `{ pcall(action) }` + `unpack(results, 2)`. Under
hide_terminal_in_new_tab that helper returns a nil terminal window in
the middle of its results; the nil is a table hole, so `#results`
reports a border before it and the trailing new-tab handle is dropped.
That left new_tab_number nil, so the tab was not closed on cleanup and
ClaudeCodeDiffOpened fired with tab_number = nil. Preserve the exact
return count via pack_results / `unpack(results, 2, results.n)`.
Add tests/unit/diff_inline_new_tab_spec.lua covering the window layout
(no empty pane, terminal hidden or shown) and the preserved tab handle.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
zakissimo
added a commit
to zakissimo/nvim
that referenced
this pull request
Jul 9, 2026
Configure claudecode.nvim to open the unified diff in a new tab with the terminal hidden for full-width review. Pin the plugin to a personal fork that fixes the empty [No Name] pane and the dropped new-tab handle in that path (coder/claudecode.nvim#303); revert to coder/claudecode.nvim once it merges. opts is present so lazy calls setup() directly, replacing the old config wrapper and its ClaudeCodeDiffOpened workaround autocmd. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
When the unified diff opens in a new tab (
diff_opts = { layout = "unified", open_in_new_tab = true }), the tab contained an extra empty[No Name]pane next to the diff, and — withhide_terminal_in_new_tab = true— the diff's tab could also leak on cleanup. Both stem fromdiff_inline.setup_inline_diff.Root cause
1. Empty pane.
:tabnew(viadisplay_terminal_in_new_tab) creates the tab with an ephemeral[No Name]window.setup_inline_diffthen picks that window aseditor_winand doesrightbelow vsplitto place the diff beside it, so the empty[No Name]window lingers as a blank pane andwincmd =gives it equal width.2. Dropped new-tab handle.
guard_inline_setupcaptured the helper's return values with:Under
hide_terminal_in_new_tab = true,display_terminal_in_new_tabreturnsnilfor the terminal window in the middle of its result list (original_tab, nil, had_terminal, new_tab). Thatnilis a table hole, so#resultsreports a border before it andunpack(results, 2)truncates — silently dropping the trailing new-tab handle. Result:new_tab_numberisnil, so the tab isn't closed incleanup_inline_diff, andClaudeCodeDiffOpenedfires withtab_number = nil(breaking the documented "own the layout" hook for this path).Fix
:tabnewwindow as the diff window whencreated_new_tabis true (its buffer isbufhidden=wipe, so it self-cleans). The in-current-tab path keeps therightbelow vsplitso it never replaces the user's own buffer.pack_resultshelper that records the exact argument count, and switch the guard tounpack(results, 2, results.n)sonils in the middle no longer truncate the returns.Reproduction
Have Claude Code propose an edit. Before: the diff tab shows an empty pane on the left. After: the diff spans the tab (terminal shown → diff + terminal, no empty pane).
Testing
tests/unit/diff_inline_new_tab_spec.luaasserts the new tab has exactly the expected windows (no empty pane) for hidden/shown terminal, and thatnew_tab_numberis tracked (notnil). It fails on the pre-fix code and passes after.diff_inline_spec.luaanddiff_hide_terminal_new_tab_spec.luastill pass.🤖 Generated with Claude Code