How to customize buffer delete when delete file?
Hey :wave: Thanks for your cool plugin. I recognized that if I delete a file where an associated buffer is still shown in an open window, this window gets closed. I guess that is by the default behavior of how NeoVim deletes buffers. Therefore I use the plugin sayonara. How can I make this also used when deleting files? Thanks for your help!
are you asking to keep the buffers open ?
i do close the windows when a file is removed because it causes issues with the nvim instance when saving the file
are you asking to keep the buffers open ?
No, but the windows. I think the default behavior of Vim on removing buffers is stupid, so I changed it. Would be cool to be able to stick to it here was well.
So let's take an example. I have one "main" window open and aside this plugin. I have a couple of buffers loaded. Now I delete the file in Lua Tree that has an associated buffer currently displayed in the main window. As result this closes the main window and I end up with just the Lua Tree. If I would have enabled to close Vim if Lua Tree is the last window, this would even close Vim at all. Instead I would like to keep my window layout (maybe a couple more), the buffer for the deleted file gets removed, but the window remains and the next buffer in the list gets displayed. I would not expect you to implement this. Therefore other minimal plugins (as the linked one) exist. But it would be great if you allow the user to somehow intersect here to customize it.
i think it would be possible. I do not have much time lately to work on opensource projects, so if you want to give it a shot ,go for it :). There might be one line to remove. Basically i prefer deleting the windows because it throws errors everywhere when editing the buffer.
We can use a custom action to do something like this:
{ key = "d", action = "sayonara_remove", action_cb = sayonara_remove, },
local function sayonara_remove(node)
-- foreach window containing the buffer for node.absolute_path
vim.cmd "wincmd 1111"
vim.cmd ":Sayonara!"
-- endfor
require("nvim-tree.actions.remove-file").fn(node)
end
You'll need to write that window iterator yourself. It would be great if Sayonara accepted a bufnr as an argument ;)
Thanks for letting me know about Sayonara... deleting/wiping buffers has always been horrible in vim.
I've been using something like this in my neovim config instead of sayonara and others, not directly related to nvim-tree but just to show it's easy to fix default neovim functionality by roughly 40 lines of code. I think it would be easy to implement this inside nvim-tree but sadly I don't have time to do it right now. But basically it tries to find an alternative buffer to show for that window before removing it with :bdelete, so window can remain in place.
-- Remove current buffer without losing window layout.
api.nvim_set_keymap.map(
'n',
'\\q',
"<Cmd>lua require('kutsan/mappings/normal/bufremove').bufremove({ force = false })<CR>",
{ silent = true, noremap = true, }
)
api.nvim_set_keymap.map(
'n',
'\\Q',
"<Cmd>lua require('kutsan/mappings/normal/bufremove').bufremove({ force = true })<CR>",
{ silent = true, noremap = true, }
)
local api = vim.api
local fn = vim.fn
local cmd = vim.cmd
local function bufremove(opts)
local target_buf_id = api.nvim_get_current_buf()
-- Do nothing if buffer is in modified state.
if not opts.force and api.nvim_buf_get_option(target_buf_id, 'modified') then
return false
end
-- Hide target buffer from all windows.
vim.tbl_map(function(win_id)
win_id = win_id or 0
local current_buf_id = api.nvim_win_get_buf(win_id)
api.nvim_win_call(win_id, function()
-- Try using alternate buffer
local alt_buf_id = fn.bufnr('#')
if alt_buf_id ~= current_buf_id and fn.buflisted(alt_buf_id) == 1 then
api.nvim_win_set_buf(win_id, alt_buf_id)
return
end
-- Try using previous buffer
cmd('bprevious')
if current_buf_id ~= api.nvim_win_get_buf(win_id) then
return
end
-- Create new listed scratch buffer
local new_buf = api.nvim_create_buf(true, true)
api.nvim_win_set_buf(win_id, new_buf)
end)
return true
end, fn.win_findbuf(target_buf_id))
cmd(string.format('bdelete%s %d', opts.force and '!' or '', target_buf_id))
end
return { bufremove = bufremove }
It sounds like you have a great solution there @kutsan
Any chance you could write up your RECIPE on the wiki?
It might also be worth checking out https://github.com/qpkorr/vim-bufkill