Skip to content

Commit 4ed8eb7

Browse files
committed
feat(fb_actions.trash): add trash action
This action attempts to find a common trash executable (currently "trash" or "gio" in that order) and performs a blocking system call via vim.fn.system to trash each file or directory selected in the file browser. Like actions.remove, refuses to trash parent directory or current working directory.
1 parent 8646e46 commit 4ed8eb7

File tree

1 file changed

+88
-0
lines changed

1 file changed

+88
-0
lines changed

lua/telescope/_extensions/file_browser/actions.lua

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,94 @@ fb_actions.remove = function(prompt_bufnr)
482482
end)
483483
end
484484

485+
--- Trash file or folders via a pre-installed trash utility for |telescope-file-browser.picker.file_browser|.<br>
486+
--- Note: Attempts to find "trash" or "gio" executable and performs a blocking system command.
487+
---@param prompt_bufnr number: The prompt bufnr
488+
fb_actions.trash = function(prompt_bufnr)
489+
local current_picker = action_state.get_current_picker(prompt_bufnr)
490+
local finder = current_picker.finder
491+
local quiet = current_picker.finder.quiet
492+
local trash_cmd = nil
493+
if vim.fn.executable("trash") == 1 then
494+
trash_cmd = "trash"
495+
elseif vim.fn.executable("gio") == 1 then
496+
trash_cmd = "gio"
497+
end
498+
if not trash_cmd then
499+
fb_utils.notify("actions.trash", { msg = "Cannot locate a valid trash executable!", level = "WARN", quiet = quiet })
500+
return
501+
end
502+
local selections = fb_utils.get_selected_files(prompt_bufnr, true)
503+
if vim.tbl_isempty(selections) then
504+
fb_utils.notify("actions.trash", { msg = "No selection to be trashed!", level = "WARN", quiet = quiet })
505+
return
506+
end
507+
508+
local files = vim.tbl_map(function(sel)
509+
return sel.filename:sub(#sel:parent().filename + 2)
510+
end, selections)
511+
512+
for _, sel in ipairs(selections) do
513+
if sel:is_dir() then
514+
local abs = sel:absolute()
515+
local msg
516+
if finder.files and Path:new(finder.path):parent():absolute() == abs then
517+
msg = "Parent folder cannot be trashed!"
518+
end
519+
if not finder.files and Path:new(finder.cwd):absolute() == abs then
520+
msg = "Current folder cannot be trashed!"
521+
end
522+
if msg then
523+
fb_utils.notify("actions.trash", { msg = msg .. " Prematurely aborting.", level = "WARN", quiet = quiet })
524+
return
525+
end
526+
end
527+
end
528+
529+
local trashed = {}
530+
531+
local message = "Selections to be trashed: " .. table.concat(files, ", ")
532+
fb_utils.notify("actions.trash", { msg = message, level = "INFO", quiet = quiet })
533+
-- TODO fix default vim.ui.input and nvim-notify 'selections to be deleted' message
534+
vim.ui.input({ prompt = "Trash selections [y/N]: " }, function(input)
535+
vim.cmd [[ redraw ]] -- redraw to clear out vim.ui.prompt to avoid hit-enter prompt
536+
if input and input:lower() == "y" then
537+
for _, p in ipairs(selections) do
538+
local is_dir = p:is_dir()
539+
local cmd = nil
540+
if trash_cmd == "gio" then
541+
cmd = { "gio", "trash", "--", p:absolute() }
542+
else
543+
cmd = { trash_cmd, "--", p:absolute() }
544+
end
545+
vim.fn.system(cmd)
546+
if vim.v.shell_error == 0 then
547+
table.insert(trashed, p.filename:sub(#p:parent().filename + 2))
548+
-- clean up opened buffers
549+
if not is_dir then
550+
fb_utils.delete_buf(p:absolute())
551+
else
552+
fb_utils.delete_dir_buf(p:absolute())
553+
end
554+
else
555+
local msg = "Command failed: " .. table.concat(cmd, " ")
556+
fb_utils.notify("actions.trash", { msg = msg, level = "WARN", quiet = quiet })
557+
end
558+
end
559+
local msg = nil
560+
if next(trashed) then
561+
msg = "Trashed: " .. table.concat(trashed, ", ")
562+
else
563+
msg = "No selections were successfully trashed"
564+
end
565+
fb_utils.notify("actions.trash", { msg = msg, level = "INFO", quiet = quiet })
566+
current_picker:refresh(current_picker.finder)
567+
else
568+
fb_utils.notify("actions.trash", { msg = "Trashing selections aborted!", level = "INFO", quiet = quiet })
569+
end
570+
end)
571+
end
572+
485573
--- Toggle hidden files or folders for |telescope-file-browser.picker.file_browser|.
486574
---@param prompt_bufnr number: The prompt bufnr
487575
fb_actions.toggle_hidden = function(prompt_bufnr)

0 commit comments

Comments
 (0)