yazi/yazi-plugin/preset/plugins/trash.lua
三咲雅 misaki masa 58f1013348
Some checks are pending
Cachix / Publish Flake (push) Waiting to run
Check / clippy (push) Waiting to run
Check / rustfmt (push) Waiting to run
Check / stylua (push) Waiting to run
Draft / build-unix (gcc-aarch64-linux-gnu, ubuntu-latest, aarch64-unknown-linux-gnu) (push) Waiting to run
Draft / build-unix (gcc-i686-linux-gnu, ubuntu-latest, i686-unknown-linux-gnu) (push) Waiting to run
Draft / build-unix (gcc-riscv64-linux-gnu, ubuntu-latest, riscv64gc-unknown-linux-gnu) (push) Waiting to run
Draft / build-unix (gcc-sparc64-linux-gnu, ubuntu-latest, sparc64-unknown-linux-gnu) (push) Waiting to run
Draft / build-unix (macos-latest, aarch64-apple-darwin) (push) Waiting to run
Draft / build-unix (macos-latest, x86_64-apple-darwin) (push) Waiting to run
Draft / build-unix (ubuntu-latest, x86_64-unknown-linux-gnu) (push) Waiting to run
Draft / build-windows (windows-latest, aarch64-pc-windows-msvc) (push) Waiting to run
Draft / build-windows (windows-latest, x86_64-pc-windows-msvc) (push) Waiting to run
Draft / build-musl (aarch64-unknown-linux-musl) (push) Waiting to run
Draft / build-musl (x86_64-unknown-linux-musl) (push) Waiting to run
Draft / build-snap (amd64, ubuntu-latest) (push) Waiting to run
Draft / build-snap (arm64, ubuntu-24.04-arm) (push) Waiting to run
Draft / snap (push) Blocked by required conditions
Draft / draft (push) Blocked by required conditions
Draft / nightly (push) Blocked by required conditions
Test / test (macos-latest) (push) Waiting to run
Test / test (ubuntu-latest) (push) Waiting to run
Test / test (windows-latest) (push) Waiting to run
feat: trash bin (#4144)
2026-07-23 01:59:39 +08:00

153 lines
3.1 KiB
Lua

local M = {}
local function top(url)
while url.parent and url.parent.name do
url = url.parent
end
return url.name and url or nil
end
local function node(url)
local top = top(url)
if not top then
return
end
return {
key = url.spec.domain,
top = top.spec.domain,
rel = url:strip_prefix(top) or Path.os(""),
}
end
local function absolute(url)
if url.is_absolute then
return fs.clean_url(url)
end
local cwd, err = fs.cwd()
if not cwd then
return nil, err
end
local root = cwd.path
while root.parent do
root = root.parent
end
return fs.clean_url(url:join(root:join(url.path)))
end
local function file(url, entry)
entry.url = url
return File(entry)
end
local function files(parent, entries)
for i, entry in ipairs(entries) do
local url = parent:join(Path.os(entry.name)):into_domain(entry.key)
entries[i] = file(url, entry)
end
return entries
end
local function notify(action, err)
ya.notify {
title = "Trash",
content = string.format("Failed to %s: %s", action, err),
level = "error",
timeout = 10,
}
end
function M:setup()
ps.sub_remote("trash-restore", function(args)
ya.async(function()
local nodes = {}
for i, arg in ipairs(args) do
nodes[i] = node(Url(arg))
if not nodes[i] then
return notify("restore", "Cannot restore the trash root")
end
end
local ok, err = fs.trash.restore(nodes)
if ok then
ya.emit("refresh", {})
else
notify("restore", err)
end
end)
end)
ps.sub_remote("trash-empty", function()
ya.async(function()
local confirmed = ya.confirm {
pos = { "center", w = 60, h = 10 },
title = ui.Line("Empty trash?"):style(th.confirm.title),
body = ui.Text("All items in the trash will be permanently deleted."),
}
if not confirmed then
return
end
local ok, err = fs.trash.empty()
if ok then
ya.emit("refresh", {})
else
notify("empty", err)
end
end)
end)
end
function M:entry()
local url, err = absolute(Url("trash:///@/."))
if url then
ya.emit("cd", { url })
else
notify("open", err)
end
end
function M:provide(job)
local op = job.op
if op == "Absolute" or op == "Canonicalize" then
return absolute(job.url)
elseif op == "Casefold" then
return job.url
elseif op == "Metadata" or op == "SymlinkMetadata" then
local n = node(job.url)
if n then
return fs.trash.metadata(n, op == "Metadata")
else
return Cha { mode = tonumber("40700", 8) }
end
elseif op == "ReadDir" then
local entries, err = fs.trash.list(node(job.url))
if entries then
return files(job.url, entries)
else
return nil, err
end
elseif op == "Revalidate" then
return fs.trash.revalidate(node(job.file.url), job.file)
elseif op == "File" then
local n = node(job.url)
if not n then
return nil, Error.custom("Cannot construct a file for the trash root")
end
local entry, err = fs.trash.entry(n)
if entry then
return file(job.url, entry)
else
return nil, err
end
elseif op == "RemoveFile" then
return fs.trash.remove("file", node(job.url))
elseif op == "RemoveDir" then
return fs.trash.remove("dir", node(job.url))
end
return false, Error.custom("Unsupported trash operation: " .. op)
end
return M