summaryrefslogtreecommitdiff
path: root/yazi/plugins/rsync.yazi/main.lua
diff options
context:
space:
mode:
Diffstat (limited to 'yazi/plugins/rsync.yazi/main.lua')
-rw-r--r--yazi/plugins/rsync.yazi/main.lua137
1 files changed, 137 insertions, 0 deletions
diff --git a/yazi/plugins/rsync.yazi/main.lua b/yazi/plugins/rsync.yazi/main.lua
new file mode 100644
index 0000000..ad2957e
--- /dev/null
+++ b/yazi/plugins/rsync.yazi/main.lua
@@ -0,0 +1,137 @@
+-- function borrowed from chmod.yazi plugin
+local selected_or_hovered = ya.sync(function()
+ local tab = cx.active
+ local paths = {}
+
+ -- count up selected files
+ for _, url in pairs(tab.selected) do
+ paths[#paths + 1] = tostring(url)
+ end
+
+ -- if no files are selected use the hovered file
+ -- a tab has folders which have files which have urls
+ if #paths == 0 and tab.current.hovered then
+ -- lua so we are 1 indexed
+ paths[1] = tostring(tab.current.hovered.url)
+ end
+ return paths
+end)
+
+-- Helper function to expand tilde (~) in a path
+local function expand_tilde(path)
+ if not path then
+ return nil
+ end
+
+ if path:sub(1, 1) == "~" then
+ local home = os.getenv("HOME") -- Get HOME environment variable
+ if not home then
+ -- Fallback for Windows-specific environment variables
+ home = os.getenv("USERPROFILE") -- Primary user profile directory on Windows
+ end
+ if home then
+ return home .. path:sub(2) -- Concatenate home path with the rest of the path
+ else
+ -- Fallback if HOME is not set
+ ya.notify({
+ title = "Rsync Plugin",
+ content = "Could not expand '~': HOME environment variable not set.",
+ level = "warn",
+ timeout = 5,
+ })
+ return path -- Return original path if home cannot be determined
+ end
+ end
+ return path -- Return original path if no tilde
+end
+
+return {
+ entry = function(_, job)
+ ya.mgr_emit("escape", { visual = true })
+ local remote_target = job.args and #job.args >= 1 and job.args[1] or nil
+ local remember = job.args and job.args.remember
+
+ local cache_file = os.getenv("HOME") .. "/.config/yazi/plugins/rsync.yazi/.last_target"
+
+ local cached_target = ""
+ if remember then
+ local f = io.open(cache_file, "r")
+ if f then
+ cached_target = f:read("*a"):match("^%s*(.-)%s*$")
+ f:close()
+ end
+ end
+
+ local files = selected_or_hovered()
+ if #files == 0 then
+ return ya.notify({ title = "Rsync", content = "No files selected", level = "warn", timeout = 3 })
+ end
+
+ local default_dest = remote_target or cached_target
+ if #files == 1 and remote_target ~= nil then
+ local base_name = files[1]:match("([^/]+)$")
+ default_dest = remote_target .. ":" .. base_name
+ ya.err({ default_dest = default_dest })
+ end
+
+ local dest, ok = ya.input({
+ title = "Rsync - [user]@[remote]:<destination>",
+ value = default_dest or nil,
+ pos = { "top-center", y = 3, w = 45 },
+ })
+ if ok ~= 1 then
+ return
+ end
+
+ -- Only expand tilde if it's a local path (doesn't contain ':')
+ if not dest:match(":") then
+ dest = expand_tilde(dest)
+ if not dest then
+ return
+ end -- If expand_tilde failed and returned nil
+ end
+
+ -- local cmd, err = Command("rsync"):args(files):arg(dest):stderr(Command.PIPED):output()
+ local cmd, err = Command("rsync")
+ :arg({ "-ahP", "--no-motd" })
+ :arg(files)
+ :arg(dest)
+ :stdout(Command.PIPED)
+ :stderr(Command.PIPED)
+ :output()
+ local stderr = cmd.stderr
+ local stdout = cmd.stdout
+ local return_code = cmd.status.code
+ ya.err({
+ stderr = stderr,
+ stdout = stdout,
+ err = err,
+ res = cmd.status.success,
+ return_code = return_code,
+ default_dest = default_dest,
+ })
+
+ if return_code ~= 0 then
+ ya.notify({
+ title = "Rsync Plugin",
+ content = string.format("stderr below, exit code %s\n\n%s", cmd.status.code, stderr),
+ level = "error",
+ timeout = 10,
+ })
+ else
+ ya.notify({
+ title = "Rsync Plugin",
+ content = "Rsync Completed!",
+ timeout = 3,
+ })
+
+ if remember and dest and dest ~= "" then
+ local f = io.open(cache_file, "w")
+ if f then
+ f:write(dest)
+ f:close()
+ end
+ end
+ end
+ end,
+}