In my NeoVim usage, I like to keep the window layout intact. Even when I close a buffer, I want the window that contained the buffer to remain open. I use bufdelete.nvim and it works perfectly for my requirements.
When I create a window and open a terminal in it, the terminal’s process may terminate. For example, because the command terminates or because I type exit<CR> in the terminal.
When that happens, there is a helpful message [Process exited 0] and any key closes the terminal buffer.
Question
When the terminal buffer closes, because the process in the terminal terminates, it also closes the window which contains the terminal buffer. Instead, I would like the window to stay open and not mess with my layout. Is there any way to achieve that?
I want to setup terminal buffers to behave like my other buffers.
Thank you!
Resources
There are some GitHub issues for NeoVim, but I am not skilled enough in NeoVim or Lua to make use of the information in there:
vim.api.nvim_create_autocmd('TermClose',{callback=function()
local buf=vim.api.nvim_get_current_buf()
local newbuf=vim.api.nvim_create_buf(false,true)
local windows=vim.fn.getwininfo()
for _,i in ipairs(windows) do
if i.bufnr==buf then
vim.api.nvim_win_set_buf(i.winid,newbuf)
end
end
vim.api.nvim_buf_delete(buf,{})
end})
oh wow this sparked an idea for me this is what i came up for my usage.
set_map("n", "<leader>x", function()
-- don't close tab if has only one buffer in a tab
local api = vim.api
local tabs = api.nvim_list_tabpages()
local is_terminal = api.nvim_buf_get_option(0, "buftype") == "terminal"
if #tabs > 1 and not is_terminal then
local cur_tab = api.nvim_win_get_tabpage(0)
local cur_buf = api.nvim_get_current_buf()
local tab_info = api.nvim_tabpage_list_wins(cur_tab)
local valid_bufs = {}
for _, win in ipairs(tab_info) do
if api.nvim_buf_is_valid(win) and win ~= cur_buf then
table.insert(valid_bufs, win)
end
end
if #valid_bufs < 1 then
local new_buf = api.nvim_create_buf(true, false)
table.insert(valid_bufs, new_buf)
end
api.nvim_set_current_buf(valid_bufs[1])
pcall(api.nvim_buf_delete, cur_buf, { force = is_terminal })
else
pcall(api.nvim_buf_delete, 0, { force = is_terminal })
end
end)
However, it doesn’t keep the terminal buffer around, so I cannot read the output of the process that terminated. Instead, the auto-command immediately closes the terminal buffer.
But your proposal lead me to a solution that almost works: