diff --git a/lua/treesitter-context.lua b/lua/treesitter-context.lua index ce058d30..88fb2a08 100644 --- a/lua/treesitter-context.lua +++ b/lua/treesitter-context.lua @@ -69,6 +69,10 @@ end ---@param winid integer local update_single_context = throttle_by_id(function(winid) +local update_single_context = throttle_by_id(vim.schedule_wrap(function(winid) + -- Remove leaked contexts firstly. + require('treesitter-context.render').close_leaked_contexts() + -- Since the update is performed asynchronously, the window may be closed at this moment. -- Therefore, we need to check if it is still valid. if not api.nvim_win_is_valid(winid) or vim.fn.getcmdtype() ~= '' then diff --git a/lua/treesitter-context/render.lua b/lua/treesitter-context/render.lua index 25800946..5f80ca65 100644 --- a/lua/treesitter-context/render.lua +++ b/lua/treesitter-context/render.lua @@ -386,6 +386,23 @@ end local M = {} +-- Contexts may sometimes leak due to reasons like the use of 'noautocmd'. +-- In these cases, affected windows might remain visible, and even ToggleContext +-- won't resolve the issue, as contexts are identified using parent windows. +-- Therefore, it's essential to occasionally perform garbage collection to +-- clean up these leaked contexts. +function M.close_leaked_contexts() + local all_wins = api.nvim_list_wins() + + for parent_winid, window_context in pairs(window_contexts) do + if not vim.tbl_contains(all_wins, parent_winid) then + close(window_context.context_winid) + close(window_context.gutter_winid) + window_contexts[parent_winid] = nil + end + end +end + --- @param bufnr integer --- @param winid integer --- @param ctx_ranges Range4[]