mirror of
https://github.com/folke/snacks.nvim
synced 2025-07-07 21:25:11 +00:00
feat(explorer): deal with existing buffers when renaming / deleting files. Closes #1315
This commit is contained in:
parent
5f2864e8c9
commit
6614a2c84f
3 changed files with 69 additions and 41 deletions
|
@ -12,6 +12,7 @@ M.meta = {
|
|||
|
||||
---@class snacks.bufdelete.Opts
|
||||
---@field buf? number Buffer to delete. Defaults to the current buffer
|
||||
---@field file? string Delete buffer by file name. If provided, `buf` is ignored
|
||||
---@field force? boolean Delete the buffer even if it is modified
|
||||
---@field filter? fun(buf: number): boolean Filter buffers to delete
|
||||
---@field wipe? boolean Wipe the buffer instead of deleting it (see `:h :bwipeout`)
|
||||
|
@ -37,6 +38,12 @@ function M.delete(opts)
|
|||
end
|
||||
|
||||
local buf = opts.buf or 0
|
||||
if opts.file then
|
||||
buf = vim.fn.bufnr(opts.file)
|
||||
if buf == -1 then
|
||||
return
|
||||
end
|
||||
end
|
||||
buf = buf == 0 and vim.api.nvim_get_current_buf() or buf
|
||||
|
||||
vim.api.nvim_buf_call(buf, function()
|
||||
|
|
|
@ -182,7 +182,7 @@ function M.actions.explorer_rename(picker, item)
|
|||
return
|
||||
end
|
||||
Snacks.rename.rename_file({
|
||||
file = item.file,
|
||||
from = item.file,
|
||||
on_rename = function(new, old)
|
||||
Tree:refresh(vim.fs.dirname(old))
|
||||
Tree:refresh(vim.fs.dirname(new))
|
||||
|
@ -205,12 +205,7 @@ function M.actions.explorer_move(picker)
|
|||
M.confirm("Move " .. what .. " to " .. t .. "?", function()
|
||||
for _, from in ipairs(paths) do
|
||||
local to = target .. "/" .. vim.fn.fnamemodify(from, ":t")
|
||||
Snacks.rename.on_rename_file(from, to, function()
|
||||
local ok, err = pcall(vim.fn.rename, from, to)
|
||||
if not ok then
|
||||
Snacks.notify.error("Failed to move `" .. from .. "`:\n- " .. err)
|
||||
end
|
||||
end)
|
||||
Snacks.rename.rename_file({ from = from, to = to })
|
||||
Tree:refresh(vim.fs.dirname(from))
|
||||
end
|
||||
Tree:refresh(target)
|
||||
|
@ -263,7 +258,9 @@ function M.actions.explorer_del(picker)
|
|||
M.confirm("Delete " .. what .. "?", function()
|
||||
for _, path in ipairs(paths) do
|
||||
local ok, err = pcall(vim.fn.delete, path, "rf")
|
||||
if not ok then
|
||||
if ok then
|
||||
Snacks.bufdelete({ file = path, force = true })
|
||||
else
|
||||
Snacks.notify.error("Failed to delete `" .. path .. "`:\n- " .. err)
|
||||
end
|
||||
Tree:refresh(vim.fs.dirname(path))
|
||||
|
|
|
@ -5,55 +5,79 @@ M.meta = {
|
|||
desc = "LSP-integrated file renaming with support for plugins like [neo-tree.nvim](https://github.com/nvim-neo-tree/neo-tree.nvim) and [mini.files](https://github.com/echasnovski/mini.files).",
|
||||
}
|
||||
|
||||
local uv = vim.uv or vim.loop
|
||||
|
||||
---@param path string
|
||||
local function realpath(path)
|
||||
return vim.fs.normalize(uv.fs_realpath(path) or path)
|
||||
end
|
||||
|
||||
-- Prompt for the new filename,
|
||||
-- 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? {file?: string, on_rename?: fun(new:string, old:string)}
|
||||
---@param opts? {from?: string, to?:string, on_rename?: fun(to:string, from:string, ok:boolean)}
|
||||
function M.rename_file(opts)
|
||||
opts = opts or {}
|
||||
local buf = vim.api.nvim_get_current_buf()
|
||||
if opts.file then
|
||||
buf = vim.fn.bufadd(opts.file)
|
||||
end
|
||||
local old = assert(realpath(vim.api.nvim_buf_get_name(buf)))
|
||||
local root = assert(realpath(uv.cwd() or "."))
|
||||
local from = vim.fn.fnamemodify(opts.from or opts.file or vim.api.nvim_buf_get_name(0), ":p")
|
||||
local to = opts.to and vim.fn.fnamemodify(opts.to, ":p") or nil
|
||||
|
||||
if old:find(root, 1, true) ~= 1 then
|
||||
root = vim.fn.fnamemodify(old, ":p:h")
|
||||
local function rename()
|
||||
assert(to, "to is required")
|
||||
M.on_rename_file(from, to, function()
|
||||
local ok = M._rename(from, to)
|
||||
if opts.on_rename then
|
||||
opts.on_rename(to, from, ok)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
local extra = old:sub(#root + 2)
|
||||
if to then
|
||||
return rename()
|
||||
end
|
||||
|
||||
local root = vim.fn.getcwd()
|
||||
|
||||
if from:find(root, 1, true) ~= 1 then
|
||||
root = vim.fn.fnamemodify(from, ":p:h")
|
||||
end
|
||||
|
||||
local extra = from:sub(#root + 2)
|
||||
|
||||
vim.ui.input({
|
||||
prompt = "New File Name: ",
|
||||
default = extra,
|
||||
completion = "file",
|
||||
}, function(new)
|
||||
if not new or new == "" or new == extra then
|
||||
}, function(value)
|
||||
if not value or value == "" or value == extra then
|
||||
return
|
||||
end
|
||||
new = vim.fs.normalize(root .. "/" .. new)
|
||||
vim.fn.mkdir(vim.fs.dirname(new), "p")
|
||||
M.on_rename_file(old, new, function()
|
||||
vim.fn.rename(old, new)
|
||||
if not opts.on_rename then
|
||||
vim.cmd.edit(new)
|
||||
end
|
||||
vim.api.nvim_buf_delete(buf, { force = true })
|
||||
vim.fn.delete(old)
|
||||
if opts.on_rename then
|
||||
opts.on_rename(new, old)
|
||||
end
|
||||
end)
|
||||
to = vim.fs.normalize(root .. "/" .. value)
|
||||
rename()
|
||||
end)
|
||||
end
|
||||
|
||||
--- Rename a file and update buffers
|
||||
---@param from string
|
||||
---@param to string
|
||||
---@return boolean ok
|
||||
function M._rename(from, to)
|
||||
from = vim.fn.fnamemodify(from, ":p")
|
||||
to = vim.fn.fnamemodify(to, ":p")
|
||||
-- rename the file
|
||||
local ret = vim.fn.rename(from, to)
|
||||
if ret ~= 0 then
|
||||
Snacks.notify.error("Failed to rename file: `" .. from .. "`")
|
||||
return false
|
||||
end
|
||||
|
||||
-- replace buffer in all windows
|
||||
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 })
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
--- Lets LSP clients know that a file has been renamed
|
||||
---@param from string
|
||||
---@param to string
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue