From bca6ed8b086363c072acbf823529aed617153d8d Mon Sep 17 00:00:00 2001 From: Alexander Courtis Date: Thu, 19 Jun 2025 11:42:10 +1000 Subject: [PATCH] vim: nvim-tree: track bufnr via buffer-update channel --- lua/nvim-tree.lua | 2 +- lua/nvim-tree/actions/node/open-file.lua | 2 +- lua/nvim-tree/explorer/init.lua | 2 +- lua/nvim-tree/explorer/view.lua | 55 +++++++++++++++++++++--- lua/nvim-tree/multi-instance-debug.lua | 4 +- 5 files changed, 53 insertions(+), 12 deletions(-) diff --git a/lua/nvim-tree.lua b/lua/nvim-tree.lua index 78a27a7a..45087633 100644 --- a/lua/nvim-tree.lua +++ b/lua/nvim-tree.lua @@ -668,7 +668,7 @@ function M.purge_all_state() local explorer = core.get_explorer() if explorer then explorer.view:close_all_tabs() - explorer.view:abandon_all_windows() + explorer.view:abandon_all_windows("purge_all_state") require("nvim-tree.git").purge_state() explorer:destroy() core.reset_explorer() diff --git a/lua/nvim-tree/actions/node/open-file.lua b/lua/nvim-tree/actions/node/open-file.lua index 317d3d46..987fce61 100644 --- a/lua/nvim-tree/actions/node/open-file.lua +++ b/lua/nvim-tree/actions/node/open-file.lua @@ -389,7 +389,7 @@ local function edit_in_current_buf(filename) local explorer = core.get_explorer() if explorer then - explorer.view:abandon_current_window() + explorer.view:abandon_current_window("open-file.edit_in_current_buf") end if M.relative_path then diff --git a/lua/nvim-tree/explorer/init.lua b/lua/nvim-tree/explorer/init.lua index 76d568b2..4bcd43e9 100644 --- a/lua/nvim-tree/explorer/init.lua +++ b/lua/nvim-tree/explorer/init.lua @@ -176,7 +176,7 @@ function Explorer:create_autocmds() if self.opts.actions.open_file.eject then self.view:prevent_buffer_override() else - self.view:abandon_current_window() + self.view:abandon_current_window("BufWipeout") end end, }) diff --git a/lua/nvim-tree/explorer/view.lua b/lua/nvim-tree/explorer/view.lua index 6d5f7226..70036d17 100644 --- a/lua/nvim-tree/explorer/view.lua +++ b/lua/nvim-tree/explorer/view.lua @@ -129,7 +129,18 @@ function View:create_buffer(bufnr) local tab = vim.api.nvim_get_current_tabpage() globals.BUFNR_PER_TAB[tab] = bufnr or vim.api.nvim_create_buf(false, false) - self.bufnr_by_tab[tab] = globals.BUFNR_PER_TAB[tab] + + if self.explorer.opts.experimental.multi_instance then + local tabid = tab + self.bufnr_by_tab[tabid] = globals.BUFNR_PER_TAB[tabid] + log.line("dev", "buffer channel attaching t%d b%d", tabid, self.bufnr_by_tab[tabid]) + vim.api.nvim_buf_attach(self.bufnr_by_tab[tabid], true, { + on_detach = function(op, bnr) + log.line("dev", "buffer channel %s t%d b%d", op, tabid, bnr) + end, + }) + end + vim.api.nvim_buf_set_name(self:get_bufnr("View:create_buffer1"), "NvimTree_" .. tab) bufnr = self:get_bufnr("View:create_buffer2") @@ -447,6 +458,7 @@ function View:reposition_window() end ---@private +---@param callsite string function View:set_current_win(callsite) local current_tab = vim.api.nvim_get_current_tabpage() local current_win = vim.api.nvim_get_current_win() @@ -483,19 +495,44 @@ function View:open_in_win(opts) events._dispatch_on_tree_open() end -function View:abandon_current_window() +---@param callsite string +function View:abandon_current_window(callsite) local tab = vim.api.nvim_get_current_tabpage() + + if self.explorer.opts.experimental.multi_instance then + log.line("dev", "View:abandon_current_window(%-20.20s) t%d w%s b%s member b%s %s", + callsite, + tab, + globals.TABPAGES and globals.TABPAGES.winnr or nil, + globals.BUFNR_PER_TAB[tab], + self.bufnr_by_tab[tab], + (globals.BUFNR_PER_TAB[tab] == self.bufnr_by_tab[tab]) and "" or "MISMATCH") + end + + -- TODO multi-instance kill the buffer instead of retaining + globals.BUFNR_PER_TAB[tab] = nil - self.bufnr_by_tab[tab] = nil if globals.TABPAGES[tab] then globals.TABPAGES[tab].winnr = nil end end -function View:abandon_all_windows() +---@param callsite string +function View:abandon_all_windows(callsite) for tab, _ in pairs(vim.api.nvim_list_tabpages()) do + if self.explorer.opts.experimental.multi_instance then + log.line("dev", "View:abandon_all_windows(%-20.20s) t%d w%s b%s member b%s %s", + callsite, + tab, + globals.TABPAGES and globals.TABPAGES.winnr or nil, + globals.BUFNR_PER_TAB[tab], + self.bufnr_by_tab[tab], + (globals.BUFNR_PER_TAB[tab] == self.bufnr_by_tab[tab]) and "" or "MISMATCH") + end + + -- TODO multi-instance kill the buffer instead of retaining + globals.BUFNR_PER_TAB[tab] = nil - self.bufnr_by_tab[tab] = nil if globals.TABPAGES[tab] then globals.TABPAGES[tab].winnr = nil end @@ -573,7 +610,7 @@ end --- Returns the window number for nvim-tree within the tabpage specified ---@param tabpage number|nil (optional) the number of the chosen tabpage. Defaults to current tabpage. ----@param callsite string for logging purposes +---@param callsite string ---@return number|nil function View:get_winnr(tabpage, callsite) if self.explorer.opts.experimental.multi_instance then @@ -605,7 +642,11 @@ function View:get_winnr(tabpage, callsite) end if ret ~= winid_from_bufnr then - msg = string.format("%s winid_from_bufnr w%s MISMATCH", msg, winid_from_bufnr) + if ret then + msg = string.format("%s winid_from_bufnr w%s MISMATCH", msg, winid_from_bufnr) + else + msg = string.format("%s winid_from_bufnr w%s STALE", msg, winid_from_bufnr) + end end log.line("dev", "%s", msg) diff --git a/lua/nvim-tree/multi-instance-debug.lua b/lua/nvim-tree/multi-instance-debug.lua index 55e2e3c8..5b460483 100644 --- a/lua/nvim-tree/multi-instance-debug.lua +++ b/lua/nvim-tree/multi-instance-debug.lua @@ -36,7 +36,7 @@ function M.tab_line() -- winnr, if present local tp = globals.TABPAGES[tab_id] if tp then - tl = tl .. " w" .. tp.winnr + tl = tl .. " w" .. (tp.winnr or "nil") else tl = tl .. " " end @@ -80,7 +80,7 @@ function M.tab_line() -- maybe winnr if orphan.winnr then - tl = tl .. " w" .. orphan.winnr + tl = tl .. " w" .. (orphan.winnr or "nil") else tl = tl .. " " end