@@ -20,7 +20,6 @@ local Class = require("nvim-tree.classic")
2020--- @field private padding integer
2121-- TODO multi-instance replace with single members
2222--- @field private bufnr_by_tabid table<integer , integer>
23- --- @field private winid_by_tabid table<integer , integer>
2423local View = Class :extend ()
2524
2625--- @class View
@@ -39,7 +38,6 @@ function View:new(args)
3938 self .side = (self .explorer .opts .view .side == " right" ) and " right" or " left"
4039 self .live_filter = { prev_focused_node = nil , }
4140 self .bufnr_by_tabid = {}
42- self .winid_by_tabid = {}
4341
4442 self .winopts = {
4543 relativenumber = self .explorer .opts .view .relativenumber ,
@@ -78,36 +76,49 @@ local BUFFER_OPTIONS = {
7876 { name = " swapfile" , value = false },
7977}
8078
79+ --- @private
80+ --- @param data table
81+ --- @param bufnr integer
82+ function View :log_event (data , bufnr )
83+ log .line (" dev" , " View %s\
84+ bufnr = %s\
85+ vim.api.nvim_get_current_tabpage() = %s\
86+ vim.api.nvim_get_current_win() = %s\
87+ self.bufnr_by_tabid = %s\
88+ globals.BUFNR_BY_TABID = %s\
89+ globals.WINID_BY_TABID = %s\
90+ vim.fn.win_findbuf(bufnr) = %s\
91+ data = %s\
92+ vim.v.event = %s" ,
93+ data .event ,
94+ bufnr ,
95+ vim .api .nvim_get_current_tabpage (),
96+ vim .api .nvim_get_current_win (),
97+ vim .inspect (self .bufnr_by_tabid , { newline = " " }),
98+ vim .inspect (globals .BUFNR_BY_TABID , { newline = " " }),
99+ vim .inspect (globals .WINID_BY_TABID , { newline = " " }),
100+ vim .inspect (vim .fn .win_findbuf (bufnr ), { newline = " " }),
101+ vim .inspect (data , { newline = " " }),
102+ vim .inspect (vim .v .event , { newline = " " })
103+ )
104+ end
105+
81106--- Buffer local autocommands to track state, deleted on buffer wipeout
82107--- @private
83108--- @param bufnr integer
84109function View :create_autocmds (bufnr )
85- -- clear bufnr and winid
86110 -- eject buffer opened in the nvim-tree window and create a new buffer
87111 vim .api .nvim_create_autocmd (" BufWipeout" , {
88112 group = self .explorer .augroup_id ,
89113 buffer = bufnr ,
90114 callback = function (data )
91- log .line (" dev" ,
92- " View BufWipeout\n bufnr = %s\n data.buf = %s\n self.bufnr_by_tabid = %s\n self.winid_by_tabid = %s" ,
93- bufnr ,
94- data .buf ,
95- vim .inspect (self .bufnr_by_tabid , { newline = " " }),
96- vim .inspect (self .winid_by_tabid , { newline = " " }),
97- vim .inspect (data , { newline = " " })
98- )
115+ self :log_event (data , bufnr )
99116
100117 -- clear the tab's buffer
101118 self .bufnr_by_tabid = vim .tbl_map (function (b )
102119 return b ~= bufnr and b or nil
103120 end , self .bufnr_by_tabid )
104121
105- -- clear the tab's window(s)
106- local winids = vim .fn .win_findbuf (bufnr )
107- self .winid_by_tabid = vim .tbl_map (function (winid )
108- return not vim .tbl_contains (winids , winid ) and winid or nil
109- end , self .winid_by_tabid )
110-
111122 if self .explorer .opts .actions .open_file .eject then
112123 self :prevent_buffer_override ()
113124 else
@@ -116,26 +127,59 @@ function View:create_autocmds(bufnr)
116127 end ,
117128 })
118129
119- -- set winid
120- vim .api .nvim_create_autocmd (" BufWinEnter" , {
130+ -- not fired when entering the first window, only subsequent event such as following a split
131+ -- does fire on :tabnew for _any_ buffer
132+ vim .api .nvim_create_autocmd (" WinEnter" , {
121133 group = self .explorer .augroup_id ,
122134 buffer = bufnr ,
123135 callback = function (data )
124- local tabid = vim . api . nvim_get_current_tabpage ( )
136+ self : log_event ( data , bufnr )
125137
126- log .line (" dev" ,
127- " View BufWinEnter\n bufnr = %s\n data.buf = %s\n self.bufnr_by_tabid = %s\n self.winid_by_tabid = %s" ,
128- bufnr ,
129- data .buf ,
130- vim .inspect (self .bufnr_by_tabid , { newline = " " }),
131- vim .inspect (self .winid_by_tabid , { newline = " " })
132- )
138+ -- ignore other buffers
139+ if data .buf ~= bufnr then
140+ return
141+ end
133142
134- self .winid_by_tabid [tabid ] = vim .fn .bufwinid (data .buf ) -- first on current tabpage
143+ -- ignore other tabs
144+ -- this event is fired on a a :tabnew window, even though the buffer isn't actually present
145+ local tabid_cur = vim .api .nvim_get_current_tabpage ()
146+ if self .bufnr_by_tabid [tabid_cur ] ~= bufnr then
147+ return
148+ end
149+
150+ -- close other windows in this tab
151+ self :close_other_windows (bufnr )
135152 end ,
136153 })
137154end
138155
156+ --- Close any other windows containing this buffer and setup current window
157+ --- Feature gated behind experimental.close_other_windows_in_tab
158+ --- @param bufnr integer
159+ function View :close_other_windows (bufnr )
160+ if not self .explorer .opts .experimental .close_other_windows_in_tab then
161+ return
162+ end
163+
164+ -- are there any other windows containing bufnr?
165+ local winids_buf = vim .fn .win_findbuf (bufnr )
166+ if # winids_buf <= 1 then
167+ return
168+ end
169+
170+ -- close all other windows
171+ local winid_cur = vim .api .nvim_get_current_win ()
172+ for _ , winid in ipairs (winids_buf ) do
173+ if winid ~= winid_cur then
174+ pcall (vim .api .nvim_win_close , winid , false )
175+ end
176+ end
177+
178+ -- setup current window, it may be new e.g. split
179+ self :set_window_options_and_buffer ()
180+ self :resize ()
181+ end
182+
139183-- TODO multi-instance remove this; delete buffers rather than retaining them
140184--- @private
141185--- @param bufnr integer
0 commit comments