From e9235b38513b40d64e41bdc04c139d6847d446d7 Mon Sep 17 00:00:00 2001 From: Anton Rybianov Date: Sun, 17 Nov 2024 20:08:06 +0300 Subject: [PATCH] fix: close leaked contexts periodically --- lua/treesitter-context.lua | 10 +++++++++- lua/treesitter-context/render.lua | 28 ++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/lua/treesitter-context.lua b/lua/treesitter-context.lua index ce058d30..32e9d431 100644 --- a/lua/treesitter-context.lua +++ b/lua/treesitter-context.lua @@ -69,6 +69,14 @@ end ---@param winid integer local update_single_context = throttle_by_id(function(winid) + -- Remove leaked contexts firstly. + local current_win = api.nvim_get_current_win() + if config.multiwindow then + require('treesitter-context.render').close_leaked_contexts() + else + require('treesitter-context.render').close_other_contexts(current_win) + end + -- 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 @@ -77,7 +85,7 @@ local update_single_context = throttle_by_id(function(winid) local bufnr = api.nvim_win_get_buf(winid) - if cannot_open(bufnr, winid) or not config.multiwindow and winid ~= api.nvim_get_current_win() then + if cannot_open(bufnr, winid) or not config.multiwindow and winid ~= current_win then require('treesitter-context.render').close(winid) return end diff --git a/lua/treesitter-context/render.lua b/lua/treesitter-context/render.lua index 25800946..090aac65 100644 --- a/lua/treesitter-context/render.lua +++ b/lua/treesitter-context/render.lua @@ -386,6 +386,34 @@ 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 winid integer The only window for which the context should be displayed. +function M.close_other_contexts(winid) + for parent_winid, window_context in pairs(window_contexts) do + if parent_winid ~= 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[]