[Snacks explorer] Moving files with unsaved changes #2852
|
Moving a file that has unsaved changes using the snacks explorer just nukes the changes without even a warning. Is this a limitation or is there a way to configure it so that it will either
And is there a way to recover the lost changes after moving a file? (probably not but idk) |
Replies: 1 comment 5 replies
Maybe the Alternatively, it can simply be renamed to an empty string and assigned Caution Saving a renamed buffer prompts Example patch (NO WARRANTY)diff --git a/lua/snacks/explorer/actions.lua b/lua/snacks/explorer/actions.lua
index 410ff8d..8bafb8c 100644
--- a/lua/snacks/explorer/actions.lua
+++ b/lua/snacks/explorer/actions.lua
@@ -227,10 +227,12 @@ function M.actions.explorer_rename(picker, item)
end
Snacks.rename.rename_file({
from = item.file,
- on_rename = function(new, old)
- Tree:refresh(vim.fs.dirname(old))
- Tree:refresh(vim.fs.dirname(new))
- M.update(picker, { target = new })
+ on_rename = function(new, old, ok)
+ if ok then
+ Tree:refresh(vim.fs.dirname(old))
+ Tree:refresh(vim.fs.dirname(new))
+ M.update(picker, { target = new })
+ end
end,
})
end
@@ -249,7 +251,7 @@ function M.actions.explorer_move(picker)
Snacks.picker.util.confirm("Move " .. what .. " to " .. t .. "?", function()
for _, from in ipairs(paths) do
local to = target .. "/" .. vim.fn.fnamemodify(from, ":t")
- Snacks.rename.rename_file({ from = from, to = to })
+ Snacks.rename.rename_file({ from = from, to = to, force = true })
Tree:refresh(vim.fs.dirname(from))
end
Tree:refresh(target)
diff --git a/lua/snacks/rename.lua b/lua/snacks/rename.lua
index 2e11ffd..605c2a7 100644
--- a/lua/snacks/rename.lua
+++ b/lua/snacks/rename.lua
@@ -8,7 +8,7 @@ M.meta = {
-- Renames the provided file, or the current buffer's file.
-- Prompt for the new filename if `to` is not provided.
-- do the rename, and trigger LSP handlers
----@param opts? {from?: string, to?:string, on_rename?: fun(to:string, from:string, ok:boolean)}
+---@param opts? {from?: string, to?:string, force?:boolean, on_rename?: fun(to:string, from:string, ok:boolean)}
function M.rename_file(opts)
opts = opts or {}
local from = vim.fn.fnamemodify(opts.from or opts.file or vim.api.nvim_buf_get_name(0), ":p")
@@ -18,6 +18,13 @@ function M.rename_file(opts)
local function rename()
assert(to, "to is required")
+ -- confirm override
+ if not opts.force and vim.uv.fs_stat(to) ~= nil then
+ local _, choice = pcall(vim.fn.confirm, ("Override '%s'?"):format(to), "&Yes\n&No\n&Cancel")
+ if choice ~= 1 then
+ return false
+ end
+ end
M.on_rename_file(from, to, function()
local ok = M._rename(from, to)
if opts.on_rename then
@@ -66,19 +73,22 @@ function M._rename(from, to)
Snacks.notify.error("Failed to rename file: `" .. from .. "`")
return false
end
-
- -- replace buffer in all windows
+ -- rename the buffer
local from_buf = vim.fn.bufnr(from)
- if from_buf >= 0 then
- local to_buf = vim.fn.bufadd(to)
- vim.bo[to_buf].buflisted = true
- for _, win in ipairs(vim.fn.win_findbuf(from_buf)) do
- vim.api.nvim_win_call(win, function()
- vim.cmd("buffer " .. to_buf)
- end)
- end
- vim.api.nvim_buf_delete(from_buf, { force = true })
+ if not vim.api.nvim_buf_is_valid(from_buf) then
+ return false
+ end
+ local to_buf = vim.fn.bufnr(to)
+ if vim.api.nvim_buf_is_valid(to_buf) then
+ vim.api.nvim_buf_delete(to_buf, { force = true })
end
+ vim.api.nvim_buf_set_name(from_buf, to)
+ -- HACK: sync the buffer to avoid the "Overwrite existing file?" prompt on save
+ vim.api.nvim_buf_call(from_buf, function()
+ local mod = vim.bo.modified
+ vim.cmd("edit! | undo")
+ vim.bo.modified = mod
+ end)
return true
end
Preventive measures:
If the file is already gone:
|
Maybe the
explorer_rename/explorer_moveactions should simply rename buffers instead of creating new ones (see the patch). That would avoid cases like this.Alternatively, it can simply be renamed to an empty string and assigned
buftype=nofileto prevent any possible data loss.Caution
Saving a renamed buffer prompts
"Overwrite existing file <file>". To prevent this,:edit! | undois used to sync the buffer after renaming.Example patch (NO WARRANTY)
diff --git a/lua/snacks/explorer/actions.lua b/lu…