This is very revealing. The current toggle_diff has a bug — it checks vim.bo[buf].buftype == 'nofile', but gitsigns diff buffers have buftype = 'acwrite' (index) or 'nowrite' (HEAD), never 'nofile'. So the scratch buffer identification and cleanup never fires.
Additionally, Neovim's :diffsplit sets several window options (scrollbind, cursorbind, foldmethod='diff', foldcolumn, diff) on the original window that need to be properly restored.
Revised Plan
Here's what the corrected toggle_diff function needs to do:
Closing the diff (when vim.wo.diff is true):
- Save the current window as the one to keep.
- Iterate all windows in the tab and for each:
- If it's a gitsigns diff buffer (identified by buffer name matching
^gitsigns://), close the window with vim.api.nvim_win_close(win, true). Since the buffer has bufhidden = 'wipe', closing the window automatically wipes the buffer — no manual buf_delete needed.
- Run
diffoff on the original window to restore diff-related window options (diff, scrollbind, cursorbind, foldmethod). Neovim's :diffoff restores these to their pre-diff values.
The key fix: use vim.api.nvim_buf_get_name(buf):match('^gitsigns://') instead of vim.bo[buf].buftype == 'nofile'.
Opening the diff (when vim.wo.diff is false):
Same as before — call gs.diffthis(ref).
Updated code
local function toggle_diff(ref)
if vim.wo.diff then
local cur_win = vim.api.nvim_get_current_win()
local tabpage = vim.api.nvim_get_current_tabpage()
local wins = vim.api.nvim_tabpage_list_wins(tabpage)
-- Close gitsigns diff buffer windows
for _, win in ipairs(wins) do
if win ~= cur_win then
local buf = vim.api.nvim_win_get_buf(win)
local bufname = vim.api.nvim_buf_get_name(buf)
if bufname:match('^gitsigns://') then
vim.api.nvim_win_close(win, true) -- bufhidden=wipe handles buffer cleanup
end
end
end
-- Turn off diff mode on the original window (restores scrollbind, cursorbind, foldmethod, etc.)
vim.cmd('diffoff')
else
package.loaded.gitsigns.diffthis(ref)
end
end
Why this is better
- Correct identification: matches
gitsigns:// buffer name instead of wrong buftype check
- No manual buf_delete: gitsigns sets
bufhidden = 'wipe', so closing the window auto-wipes the buffer
- Proper option restore:
diffoff on the remaining window restores scrollbind, cursorbind, foldmethod, foldcolumn to their pre-diff state
- Simpler: no need to iterate all windows for
diffoff — just close the diff windows first, then diffoff on the current (original) window
Shall I proceed with the implementation?