Skip to content

Commit 7eadf08

Browse files
authored
fix: implement proper check for close_if_last_window (#1830)
1 parent e858a44 commit 7eadf08

File tree

3 files changed

+81
-65
lines changed

3 files changed

+81
-65
lines changed

lua/neo-tree.lua

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ M.ensure_config = function()
2222
return M.config
2323
end
2424

25+
---A performance-focused version for checking a specific key of a config while trying not to do expensive setup work
26+
---@return neotree.Config.Base
27+
M.peek_config = function()
28+
return new_user_config or M.ensure_config()
29+
end
30+
2531
---@param ignore_filetypes string[]?
2632
---@param ignore_winfixbuf boolean?
2733
M.get_prior_window = function(ignore_filetypes, ignore_winfixbuf)

lua/neo-tree/setup/init.lua

Lines changed: 1 addition & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -272,77 +272,14 @@ M.buffer_enter_event = function()
272272
end
273273
end
274274

275-
---@type boolean?
276-
local curwin_floating = nil
277275
M.win_enter_event = function()
278276
local win_id = vim.api.nvim_get_current_win()
279-
local previous_window_floating = curwin_floating
280-
curwin_floating = utils.is_floating(win_id)
281-
if curwin_floating then
277+
if utils.is_floating(win_id) then
282278
return
283279
end
284-
285280
-- if the new win is not a floating window, make sure all neo-tree floats are closed
286281
manager.close_all("float")
287282

288-
if M.config.close_if_last_window then
289-
local tabid = vim.api.nvim_get_current_tabpage()
290-
local wins = utils.prior_windows[tabid]
291-
local prior_exists = utils.truthy(wins)
292-
local non_floating_wins = vim.tbl_filter(function(win)
293-
return not utils.is_floating(win)
294-
end, vim.api.nvim_tabpage_list_wins(tabid))
295-
local win_count = #non_floating_wins
296-
log.trace("checking if last window")
297-
log.trace("prior window exists = ", prior_exists)
298-
log.trace("win_count: ", win_count)
299-
if
300-
prior_exists
301-
and win_count == 1
302-
and vim.o.filetype == "neo-tree"
303-
-- if neo-tree managed to stay open long enough for users to open popups, (e.g. other windows automatically closed
304-
-- w/o triggering new WinEnter events), we shouldn't close even if it is technically the last window
305-
and not previous_window_floating
306-
then
307-
local position = vim.b[0].neo_tree_position
308-
local source = vim.b[0].neo_tree_source
309-
-- close_if_last_window just doesn't make sense for a split style
310-
if position ~= "current" then
311-
log.trace("last window, closing")
312-
local state = require("neo-tree.sources.manager").get_state(source)
313-
if state == nil then
314-
return
315-
end
316-
local mod = utils.get_opened_buffers()
317-
log.debug("close_if_last_window, modified files found: ", vim.inspect(mod))
318-
for filename, buf_info in pairs(mod) do
319-
if buf_info.modified then
320-
local buf_name, message
321-
if vim.startswith(filename, "[No Name]#") then
322-
buf_name = string.sub(filename, 11)
323-
message =
324-
"Cannot close because an unnamed buffer is modified. Please save or discard this file."
325-
else
326-
buf_name = filename
327-
message =
328-
"Cannot close because one of the files is modified. Please save or discard changes."
329-
end
330-
log.trace("close_if_last_window, showing unnamed modified buffer: ", filename)
331-
vim.schedule(function()
332-
log.warn(message)
333-
vim.cmd("rightbelow vertical split")
334-
vim.api.nvim_win_set_width(win_id, state.window.width or 40)
335-
vim.cmd("b " .. buf_name)
336-
end)
337-
return
338-
end
339-
end
340-
vim.cmd("q!")
341-
return
342-
end
343-
end
344-
end
345-
346283
if vim.o.filetype == "neo-tree" then
347284
local _, position = pcall(vim.api.nvim_buf_get_var, 0, "neo_tree_position")
348285
if position == "current" then

plugin/neo-tree.lua

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,21 @@ local function try_netrw_hijack(path)
2525
return require("neo-tree.setup.netrw").hijack()
2626
end
2727

28-
local augroup = vim.api.nvim_create_augroup("NeoTree_NetrwDeferred", { clear = true })
28+
local augroup = vim.api.nvim_create_augroup("NeoTree", { clear = true })
2929

3030
-- lazy load until bufenter/netrw hijack
3131
vim.api.nvim_create_autocmd({ "BufEnter" }, {
3232
group = augroup,
33+
desc = "Lazy-load until bufenter/opened dir",
3334
callback = function(args)
3435
return vim.g.neotree_watching_bufenter == 1 or try_netrw_hijack(args.file)
3536
end,
3637
})
3738

3839
-- track window order
3940
vim.api.nvim_create_autocmd({ "WinEnter" }, {
41+
group = augroup,
42+
desc = "Track prior windows for opening intuitiveness",
4043
callback = function(ev)
4144
local win = vim.api.nvim_get_current_win()
4245
local utils = require("neo-tree.utils")
@@ -73,11 +76,81 @@ vim.api.nvim_create_autocmd({ "WinEnter" }, {
7376

7477
-- setup session loading
7578
vim.api.nvim_create_autocmd("SessionLoadPost", {
79+
group = augroup,
80+
desc = "Session loading",
7681
callback = function()
7782
if require("neo-tree").ensure_config().auto_clean_after_session_restore then
7883
require("neo-tree.ui.renderer").clean_invalid_neotree_buffers(true)
7984
end
8085
end,
8186
})
8287

88+
vim.api.nvim_create_autocmd("WinClosed", {
89+
group = augroup,
90+
desc = "close_if_last_window autocmd",
91+
callback = function(args)
92+
local closing_win = tonumber(args.match)
93+
local visible_winids = vim.api.nvim_tabpage_list_wins(0)
94+
local other_panes = {}
95+
local utils = require("neo-tree.utils")
96+
for _, winid in ipairs(visible_winids) do
97+
if not utils.is_floating(winid) and winid ~= closing_win then
98+
other_panes[#other_panes + 1] = winid
99+
end
100+
end
101+
102+
if #other_panes ~= 1 then
103+
return
104+
end
105+
106+
local remaining_pane = other_panes[1]
107+
local remaining_buf = vim.api.nvim_win_get_buf(remaining_pane)
108+
109+
if vim.bo[remaining_buf].filetype ~= "neo-tree" then
110+
return
111+
end
112+
113+
local position = vim.b[remaining_buf].neo_tree_position
114+
local source = vim.b[remaining_buf].neo_tree_source
115+
-- close_if_last_window just doesn't make sense for a split style
116+
if position == "current" then
117+
return
118+
end
119+
120+
local log = require("neo-tree.log")
121+
log.trace("last window, closing")
122+
local state = require("neo-tree.sources.manager").get_state(source)
123+
if not state then
124+
return
125+
end
126+
if not require("neo-tree").ensure_config().close_if_last_window then
127+
return
128+
end
129+
local mod = utils.get_opened_buffers()
130+
log.debug("close_if_last_window, modified files found: ", vim.inspect(mod))
131+
for filename, buf_info in pairs(mod) do
132+
if buf_info.modified then
133+
local buf_name, message
134+
if vim.startswith(filename, "[No Name]#") then
135+
buf_name = string.sub(filename, 11)
136+
message =
137+
"Cannot close because an unnamed buffer is modified. Please save or discard this file."
138+
else
139+
buf_name = filename
140+
message =
141+
"Cannot close because one of the files is modified. Please save or discard changes."
142+
end
143+
log.trace("close_if_last_window, showing unnamed modified buffer: ", filename)
144+
vim.schedule(function()
145+
log.warn(message)
146+
vim.cmd("rightbelow vertical split")
147+
vim.api.nvim_win_set_width(0, state.window.width or 40)
148+
vim.cmd("b " .. buf_name)
149+
end)
150+
return
151+
end
152+
end
153+
end,
154+
})
155+
83156
vim.g.loaded_neo_tree = 1

0 commit comments

Comments
 (0)