-
-
Notifications
You must be signed in to change notification settings - Fork 610
Auto Close
Elias Assaf edited this page Feb 27, 2023
·
10 revisions
A desirable feature is to close the tab/nvim when nvim-tree is the last window.
Unfortunately such functionality is problematic and is not present in nvim-tree:
- vim events are the only mechanism we can use for auto close
- vim events are unpredictably ordered, especially when other plugins and automation are involved
-
BufEnter
is the last event that can be acted upon and that event can have side effects - Event nesting may be disabled by other plugins / automation, resulting in missing events
This is a minimal viable solution that will achieve the auto close functionality.
vim.api.nvim_create_autocmd("BufEnter", {
nested = true,
callback = function()
if #vim.api.nvim_list_wins() == 1 and require("nvim-tree.utils").is_nvim_tree_buf() then
vim.cmd "quit"
end
end
})
It will likely fail for most complex nvim setups. Consider this a starting point.
You could adopt the complete solutions developed by users.
This will:
- Close the tab if nvim-tree is the last buffer in the tab (after closing a buffer)
- Close vim if nvim-tree is the last buffer (after closing a buffer)
- Close nvim-tree across all tabs when one nvim-tree buffer is manually closed if and only if
tabs.sync.close
is set.
local function tab_win_closed(winnr)
local api = require"nvim-tree.api"
local tabnr = vim.api.nvim_win_get_tabpage(winnr)
local bufnr = vim.api.nvim_win_get_buf(winnr)
local buf_info = vim.fn.getbufinfo(bufnr)[1]
local tab_wins = vim.tbl_filter(function(w) return w~=winnr end, vim.api.nvim_tabpage_list_wins(tabnr))
local tab_bufs = vim.tbl_map(vim.api.nvim_win_get_buf, tab_wins)
if buf_info.name:match(".*NvimTree_%d*$") then -- close buffer was nvim tree
-- Close all nvim tree on :q
if not vim.tbl_isempty(tab_bufs) then -- and was not the last window (not closed automatically by code below)
api.tree.close()
end
else -- else closed buffer was normal buffer
if #tab_bufs == 1 then -- if there is only 1 buffer left in the tab
local last_buf_info = vim.fn.getbufinfo(tab_bufs[1])[1]
if last_buf_info.name:match(".*NvimTree_%d*$") then -- and that buffer is nvim tree
vim.schedule(function ()
if #vim.api.nvim_list_wins() == 1 then -- if its the last buffer in vim
vim.cmd "quit" -- then close all of vim
else -- else there are more tabs open
vim.api.nvim_win_close(tab_wins[1], true) -- then close only the tab
end
end)
end
end
end
end
vim.api.nvim_create_autocmd("WinClosed", {
callback = function ()
local winnr = tonumber(vim.fn.expand("<amatch>"))
vim.schedule_wrap(tab_win_closed(winnr))
end,
nested = true
})
vim.api.nvim_create_autocmd("BufEnter", {
group = vim.api.nvim_create_augroup("NvimTreeClose", {clear = true}),
pattern = "NvimTree_*",
callback = function()
local layout = vim.api.nvim_call_function("winlayout", {})
if layout[1] == "leaf" and vim.api.nvim_buf_get_option(vim.api.nvim_win_get_buf(layout[2]), "filetype") == "NvimTree" and layout[3] == nil then vim.cmd("confirm quit") end
end
})
-- nvim-tree is also there in modified buffers so this function filter it out
local modifiedBufs = function(bufs)
local t = 0
for k,v in pairs(bufs) do
if v.name:match("NvimTree_") == nil then
t = t + 1
end
end
return t
end
vim.api.nvim_create_autocmd("BufEnter", {
nested = true,
callback = function()
if #vim.api.nvim_list_wins() == 1 and
vim.api.nvim_buf_get_name(0):match("NvimTree_") ~= nil and
modifiedBufs(vim.fn.getbufinfo({bufmodified = 1})) == 0 then
vim.cmd "quit"
end
end
})
Key binds solution, should not conflict with other plugins.
local function close_buffer_and_nvimtree(buffer_cmd, last_window_cmd)
local tree = require("nvim-tree.api").tree
local buffer_count = #vim.fn.filter(vim.fn.range(1, vim.fn.bufnr '$'), 'buflisted(v:val)')
local command = buffer_count > 1 and buffer_cmd or last_window_cmd
tree.toggle({ focus = false })
local success, errorMsg = pcall(api.nvim_command, command)
if not success then
print("Failed to quit: " .. errorMsg)
end
tree.toggle({ focus = false })
if buffer_count == 1 and #vim.api.nvim_list_wins() == 1 and require("nvim-tree.utils").is_nvim_tree_buf() then
vim.cmd("quit")
end
end
map("n", "<Leader>q", function()
close_buffer_and_nvimtree("bd", "q")
end, { noremap = true, silent = true })
map("n", "<Leader>x", function()
close_buffer_and_nvimtree("bd!", "q!")
end, { noremap = true, silent = true })
A simple solution that uses the QuitPre event:
vim.api.nvim_create_autocmd({"QuitPre"}, {
callback = function() vim.cmd("NvimTreeClose") end,
})