mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-22 23:31:05 +00:00
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
153 lines
3.1 KiB
Lua
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
|