diff --git a/init.lua b/init.lua index b6b1ae3..bcfe1ee 100644 --- a/init.lua +++ b/init.lua @@ -504,5 +504,53 @@ vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI', 'InsertEnter', 'Ins vim.keymap.set('n', '', 'echo ""', { noremap = true, silent = true }) vim.keymap.set('v', '', 'echo ""', { noremap = true, silent = true }) +-- When a file is deleted externally, rename all its buffers to "[file]: file removed" +vim.api.nvim_create_autocmd({ 'BufEnter', 'BufWritePost' }, { + callback = function() + local current_buf = vim.api.nvim_get_current_buf() + local ft = vim.api.nvim_buf_get_option(current_buf, 'filetype') + local current_name = vim.api.nvim_buf_get_name(current_buf) + -- Skip Neo-tree, unnamed, or already-marked buffers + if ft == 'neo-tree' or current_name == '' or current_name:match 'file removed' then + return + end + -- If this file no longer exists, mark all buffers showing it + if vim.fn.filereadable(current_name) == 0 then + local filename = vim.fn.fnamemodify(current_name, ':t') + local new_name = string.format('[%s]: file removed', filename) + -- Iterate over all listed buffers + for _, buf in ipairs(vim.api.nvim_list_bufs()) do + if vim.api.nvim_buf_is_valid(buf) then + local name = vim.api.nvim_buf_get_name(buf) + if name == current_name and not name:match 'file removed' then + -- Temporarily unlist so renaming works cleanly + vim.api.nvim_buf_set_option(buf, 'buflisted', false) + vim.api.nvim_buf_set_name(buf, new_name) + vim.api.nvim_buf_set_option(buf, 'buflisted', true) + end + end + end + end + end, +}) +-- Automatically wipe "file removed" buffers when they are closed +vim.api.nvim_create_autocmd('BufWinLeave', { + callback = function(args) + local buf = args.buf + if vim.api.nvim_buf_is_valid(buf) then + local name = vim.api.nvim_buf_get_name(buf) + local marked = pcall(vim.api.nvim_buf_get_var, buf, 'marked_for_wipe') and vim.api.nvim_buf_get_var(buf, 'marked_for_wipe') + -- If the buffer was marked for wipe or name indicates it's deleted + if marked or (name ~= '' and name:match 'file removed') then + vim.schedule(function() + if vim.api.nvim_buf_is_valid(buf) then + vim.cmd('bwipeout! ' .. buf) + end + end) + end + end + end, +}) + -- The line beneath this is called `modeline`. See `:help modeline` -- vim: ts=2 sts=2 sw=2 et diff --git a/lua/plugins/custom/filetree.lua b/lua/plugins/custom/filetree.lua index fd26cf5..5525c51 100644 --- a/lua/plugins/custom/filetree.lua +++ b/lua/plugins/custom/filetree.lua @@ -10,10 +10,40 @@ return { 'MunifTanjim/nui.nvim', }, config = function() + -- Handling deleted file buffers, marking them as removed + local function delete_file_mark_removed(state) + local node = state.tree:get_node() + if not node or node.type ~= 'file' then + return true + end + local path = node.path + -- Ask for confirmation + local choice = vim.fn.confirm('Are you sure you want to delete: ' .. vim.fn.fnamemodify(path, ':t') .. '?', '&Yes\n&No', 2) + if choice ~= 1 then + return true + end -- user chose "No" + local buf_to_update = nil + for _, win in ipairs(vim.api.nvim_list_wins()) do + local buf = vim.api.nvim_win_get_buf(win) + if vim.api.nvim_buf_is_valid(buf) and vim.api.nvim_buf_get_name(buf) == path then + buf_to_update = buf + break + end + end + -- Delete file + vim.loop.fs_unlink(path) + -- Refresh Neo-tree + state.commands.refresh(state) + -- Update buffer name + if buf_to_update and vim.api.nvim_buf_is_valid(buf_to_update) then + local filename = vim.fn.fnamemodify(path, ':t') + vim.api.nvim_buf_set_name(buf_to_update, filename .. ':file removed') + end + return true + end -- Track last created file or folder local last_created_path = nil vim.api.nvim_set_hl(0, 'NeoTreeLastCreated', { fg = '#00ff00', bold = true }) - local function normalize_path(path) return vim.fn.fnamemodify(path, ':p') end @@ -160,6 +190,7 @@ return { smart_open_split(state, 'v') end, ['t'] = 'noop', + ['d'] = delete_file_mark_removed, ['a'] = function(state) -- Get the current node local node = state.tree:get_node()