mirror of
https://github.com/sxyazi/yazi.git
synced 2026-07-21 23:01:05 +00:00
129 lines
3 KiB
Lua
129 lines
3 KiB
Lua
local M = {}
|
|
|
|
local state = ya.sync(function(st)
|
|
return {
|
|
cwd = tostring(cx.active.current.cwd),
|
|
empty = st.empty,
|
|
}
|
|
end)
|
|
|
|
local set_state = ya.sync(function(st, empty) st.empty = empty end)
|
|
|
|
function M:setup(opts)
|
|
opts = opts or {}
|
|
|
|
if opts.update_db then
|
|
ps.sub("cd", function()
|
|
local cwd = cx.active.current.cwd
|
|
ya.async(function() Command("zoxide"):arg({ "add", tostring(cwd) }):status() end)
|
|
end)
|
|
end
|
|
end
|
|
|
|
function M:entry()
|
|
local st = state()
|
|
if st.empty == nil then
|
|
st.empty = M.is_empty(st.cwd)
|
|
set_state(st.empty)
|
|
end
|
|
|
|
if st.empty then
|
|
return ya.notify {
|
|
title = "Zoxide",
|
|
content = "No directory history found, check Zoxide's doc to set it up and restart Yazi.",
|
|
timeout = 5,
|
|
level = "error",
|
|
}
|
|
end
|
|
|
|
local permit = ui.hide()
|
|
local target, err = M.run_with(st.cwd)
|
|
permit:drop()
|
|
|
|
if not target then
|
|
ya.notify { title = "Zoxide", content = tostring(err), timeout = 5, level = "error" }
|
|
elseif target ~= "" then
|
|
ya.emit("cd", { target, raw = true })
|
|
end
|
|
end
|
|
|
|
function M.options()
|
|
-- https://github.com/ajeetdsouza/zoxide/blob/main/src/cmd/query.rs#L92
|
|
local default = {
|
|
-- Search mode
|
|
"--exact",
|
|
-- Search result
|
|
"--no-sort",
|
|
-- Interface
|
|
"--bind=ctrl-z:ignore,btab:up,tab:down",
|
|
"--cycle",
|
|
"--keep-right",
|
|
-- Layout
|
|
"--layout=reverse",
|
|
"--height=100%",
|
|
"--border",
|
|
"--scrollbar=▌",
|
|
"--info=inline",
|
|
-- Display
|
|
"--tabstop=1",
|
|
-- Scripting
|
|
"--exit-0",
|
|
}
|
|
|
|
if ya.target_family() == "unix" then
|
|
default[#default + 1] = "--preview-window=down,30%,sharp"
|
|
if ya.target_os() == "linux" then
|
|
default[#default + 1] = [[--preview='\command -p ls -Cp --color=always --group-directories-first {2..}']]
|
|
else
|
|
default[#default + 1] = [[--preview='\command -p ls -Cp {2..}']]
|
|
end
|
|
end
|
|
|
|
return (os.getenv("FZF_DEFAULT_OPTS") or "")
|
|
.. " "
|
|
.. table.concat(default, " ")
|
|
.. " "
|
|
.. (os.getenv("YAZI_ZOXIDE_OPTS") or "")
|
|
end
|
|
|
|
---@param cwd string
|
|
---@return boolean
|
|
function M.is_empty(cwd)
|
|
local child = Command("zoxide"):arg({ "query", "-l", "--exclude", cwd }):stdout(Command.PIPED):spawn()
|
|
if not child then
|
|
return true
|
|
end
|
|
|
|
local first = child:read_line()
|
|
child:start_kill()
|
|
return not first
|
|
end
|
|
|
|
---@param cwd string
|
|
---@return string?, Error?
|
|
function M.run_with(cwd)
|
|
local child, err = Command("zoxide")
|
|
:arg({ "query", "-i", "--exclude", cwd })
|
|
:env("SHELL", "sh")
|
|
:env("CLICOLOR", 1)
|
|
:env("CLICOLOR_FORCE", 1)
|
|
:env("_ZO_FZF_OPTS", M.options())
|
|
:stdin(Command.INHERIT)
|
|
:stdout(Command.PIPED)
|
|
:stderr(Command.PIPED)
|
|
:spawn()
|
|
|
|
if not child then
|
|
return nil, Err("Failed to start `zoxide`, error: %s", err)
|
|
end
|
|
|
|
local output, err = child:wait_with_output()
|
|
if not output then
|
|
return nil, Err("Cannot read `zoxide` output, error: %s", err)
|
|
elseif not output.status.success and output.status.code ~= 130 then
|
|
return nil, Err("`zoxide` exited with code %s: %s", output.status.code, output.stderr:gsub("^zoxide:%s*", ""))
|
|
end
|
|
return output.stdout:gsub("\n$", ""), nil
|
|
end
|
|
|
|
return M
|