commit aaec3e5b0dab1e38099abb6371724ab2b199532e
parent 25322a3a3b225c54f2fcec83654d9d2fc99ad543
Author: Tomas Slusny <slusnucky@gmail.com>
Date: Mon, 13 Oct 2025 20:12:42 +0200
fix(difftool): add check for window number when cleaning up layout #36161
- Move autocmd cleanup logic back to setup_layout as WinClosed autocmds
were triggering for every closed window even when buf scoped, and when
buf scoped, pattern filter did not work.
- Cleanup when quickfix window is closed as well to prevent state where
on closing quickfix setup_layout will reset it after with empty
content because of WinClosed autocmds triggering.
Signed-off-by: Tomas Slusny <slusnucky@gmail.com>
Diffstat:
1 file changed, 52 insertions(+), 42 deletions(-)
diff --git a/runtime/pack/dist/opt/nvim.difftool/lua/difftool.lua b/runtime/pack/dist/opt/nvim.difftool/lua/difftool.lua
@@ -28,31 +28,36 @@ local layout = {
group = nil,
left_win = nil,
right_win = nil,
+ qf_win = nil,
}
local util = require('vim._core.util')
+--- Clean up the layout state, autocmds and quickfix list
+--- @param with_qf boolean whether the layout included a quickfix window
+local function cleanup_layout(with_qf)
+ if layout.group then
+ vim.api.nvim_del_augroup_by_id(layout.group)
+ layout.group = nil
+ end
+ layout.left_win = nil
+ layout.right_win = nil
+ layout.qf_win = nil
+
+ if with_qf then
+ vim.fn.setqflist({})
+ vim.cmd.cclose()
+ end
+end
+
--- Set up a consistent layout with two diff windows
--- @param with_qf boolean whether to open the quickfix window
local function setup_layout(with_qf)
- local wins = vim.api.nvim_tabpage_list_wins(0)
local left_valid = layout.left_win and vim.api.nvim_win_is_valid(layout.left_win)
local right_valid = layout.right_win and vim.api.nvim_win_is_valid(layout.right_win)
- local wins_passed = left_valid and right_valid
-
- local qf_passed = not with_qf
- if not qf_passed and wins_passed then
- for _, win in ipairs(wins) do
- local buf = vim.api.nvim_win_get_buf(win)
- local ft = vim.bo[buf].filetype
- if ft == 'qf' then
- qf_passed = true
- break
- end
- end
- end
+ local qf_valid = layout.qf_win and vim.api.nvim_win_is_valid(layout.qf_win)
- if wins_passed and qf_passed then
+ if left_valid and right_valid and (not with_qf or qf_valid) then
return false
end
@@ -63,47 +68,52 @@ local function setup_layout(with_qf)
if with_qf then
vim.cmd('botright copen')
+ layout.qf_win = vim.api.nvim_get_current_win()
+ else
+ layout.qf_win = nil
end
vim.api.nvim_set_current_win(layout.right_win)
-end
-
---- Diff two files
---- @param left_file string
---- @param right_file string
---- @param with_qf boolean? whether to open the quickfix window
-local function diff_files(left_file, right_file, with_qf)
- setup_layout(with_qf or false)
-
- local left_buf = util.edit_in(layout.left_win, left_file)
- local right_buf = util.edit_in(layout.right_win, right_file)
-- When one of the windows is closed, clean up the layout
vim.api.nvim_create_autocmd('WinClosed', {
group = layout.group,
- buffer = left_buf,
+ pattern = tostring(layout.left_win),
callback = function()
- if layout.group and layout.left_win then
- vim.api.nvim_del_augroup_by_id(layout.group)
- layout.left_win = nil
- layout.group = nil
- vim.fn.setqflist({})
- vim.cmd.cclose()
- end
+ cleanup_layout(with_qf)
end,
})
vim.api.nvim_create_autocmd('WinClosed', {
group = layout.group,
- buffer = right_buf,
+ pattern = tostring(layout.right_win),
callback = function()
- if layout.group and layout.right_win then
- vim.api.nvim_del_augroup_by_id(layout.group)
- layout.right_win = nil
- layout.group = nil
- vim.fn.setqflist({})
- vim.cmd.cclose()
- end
+ cleanup_layout(with_qf)
end,
})
+ if with_qf then
+ vim.api.nvim_create_autocmd('WinClosed', {
+ group = layout.group,
+ pattern = tostring(layout.qf_win),
+ callback = function()
+ -- For quickfix also close one of diff windows
+ if layout.left_win and vim.api.nvim_win_is_valid(layout.left_win) then
+ vim.api.nvim_win_close(layout.left_win, true)
+ end
+
+ cleanup_layout(with_qf)
+ end,
+ })
+ end
+end
+
+--- Diff two files
+--- @param left_file string
+--- @param right_file string
+--- @param with_qf boolean? whether to open the quickfix window
+local function diff_files(left_file, right_file, with_qf)
+ setup_layout(with_qf or false)
+
+ util.edit_in(layout.left_win, left_file)
+ util.edit_in(layout.right_win, right_file)
vim.cmd('diffoff!')
vim.api.nvim_win_call(layout.left_win, vim.cmd.diffthis)