Configure synchronization of files and directories through a plugin.
made a wrapper for spawning commands
5 files changed, +78 -26
+4-0README.md
| @@ -16,6 +16,10 @@ A lightweight Neovim plugin that keeps directories in sync using `inotifywait`, | ||
| 16 | 16 | - Fully typed config for autocompletion and inline docs |
| 17 | 17 | - Automatically expands paths in the config |
| 18 | 18 | |
| 19 | +## Warning | |
| 20 | + | |
| 21 | +- Updates made in the dst will be overwritten by the updates made in src | |
| 22 | + | |
| 19 | 23 | ## Requirements |
| 20 | 24 | |
| 21 | 25 | - Linux (uses `inotifywait`) |
+0-2lua/syncmap/default.lua
| @@ -1,5 +1,3 @@ | ||
| 1 | -local expand = vim.fn.expand | |
| 2 | - | |
| 3 | 1 | ---@type FinalSyncmapOpts |
| 4 | 2 | return { |
| 5 | 3 | map = {}, |
+1-1lua/syncmap/init.lua
| @@ -17,8 +17,8 @@ function M.setup(opts) | ||
| 17 | 17 | M.rsync.opts = M.opts |
| 18 | 18 | M.log.opts = M.opts |
| 19 | 19 | M.commands.opts = M.opts |
| 20 | - M.state.sync() | |
| 21 | 20 | M.commands.setup() |
| 21 | + M.state.sync() | |
| 22 | 22 | end |
| 23 | 23 | |
| 24 | 24 | return M |
+15-23lua/syncmap/rsync.lua
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | local log = require("syncmap.log") |
| 2 | -local utils = require("syncmap.utils") | |
| 2 | +local simple_cmd = require("syncmap.simple_cmd") | |
| 3 | 3 | local M = { |
| 4 | 4 | opts = require("syncmap.default"), |
| 5 | 5 | } |
| @@ -22,16 +22,8 @@ function M.spawn_watcher(args) | ||
| 22 | 22 | if M.opts.reverse_sync_on_startup then |
| 23 | 23 | M.run(args) |
| 24 | 24 | end |
| 25 | - local cmd = string.format( | |
| 26 | - "while inotifywait -r -e modify,create,delete %q; do rsync %s %q %q; done", | |
| 27 | - args.src, | |
| 28 | - table.concat(utils.extract_flags(args.flags), " "), | |
| 29 | - args.src, | |
| 30 | - args.dst | |
| 31 | - ) | |
| 32 | 25 | |
| 33 | - local handle | |
| 34 | - handle, _ = vim.uv.spawn("sh", { | |
| 26 | + simple_cmd.spawn("sh", { | |
| 35 | 27 | args = { |
| 36 | 28 | "-c", |
| 37 | 29 | string.format( |
| @@ -42,20 +34,20 @@ function M.spawn_watcher(args) | ||
| 42 | 34 | args.dst |
| 43 | 35 | ), |
| 44 | 36 | }, |
| 45 | - stdio = { nil, nil, nil }, | |
| 37 | + path = "sh", | |
| 46 | 38 | cwd = args.src, |
| 47 | - env = vim.fn.environ(), | |
| 48 | - detached = true, | |
| 49 | - hide = true, | |
| 50 | - ---@diagnostic disable-next-line: assign-type-mismatch | |
| 51 | - uid = vim.uv.getuid(), | |
| 52 | - verbatim = false, | |
| 53 | - ---@diagnostic disable-next-line: assign-type-mismatch | |
| 54 | - gid = vim.uv.getgid(), | |
| 55 | - }, function(code, signal) | |
| 56 | - log.info(cmd .. "\nEnded with code " .. code .. " and signal " .. signal) | |
| 57 | - handle:close() | |
| 58 | - end) | |
| 39 | + callback = function(code, status, handle, pid) | |
| 40 | + log.info( | |
| 41 | + string.format( | |
| 42 | + "The process ended with %q code and status %q.\nThe pid from handle is %q.\nThe original pid is %q.", | |
| 43 | + code, | |
| 44 | + status, | |
| 45 | + handle:get_pid(), | |
| 46 | + pid | |
| 47 | + ) | |
| 48 | + ) | |
| 49 | + end, | |
| 50 | + }) | |
| 59 | 51 | end |
| 60 | 52 | |
| 61 | 53 | return M |
+58-0lua/syncmap/simple_cmd.lua
| @@ -0,0 +1,58 @@ | ||
| 1 | +local M = {} | |
| 2 | + | |
| 3 | +---@alias StdIO integer|uv.uv_stream_t|nil | |
| 4 | + | |
| 5 | +---@class SpawnCommandParams | |
| 6 | +---@field args string[] The arguments to run on the exectuable | |
| 7 | +---@field cwd? string @[default=vim.fn.getcwd()] Set the current working directory for the sub-process. | |
| 8 | +---@field env? table<string,string> @[default=vim.fn.environ()] Set environment variables for the new process. | |
| 9 | +---@field stdio? { [1]: integer|uv.uv_stream_t|nil, [2]: integer|uv.uv_stream_t|nil, [3]: integer|uv.uv_stream_t|nil } @[default={nil,nil,nil}] Set the file descriptors that will be made available to the child process. The convention is that the first entries are stdin, stdout, and stderr. (**Note**: On Windows, file descriptors after the third are available to the child process only if the child processes uses the MSVCRT runtime.) | |
| 10 | +---@field detatched? boolean @[default=true] If true, spawn the child process in a detached state - this will make it a process group leader, and will effectively enable the child to keep running after the parent exits. Note that the child process will still keep the parent's event loop alive unless the parent process calls `uv.unref()` on the child's process handle. | |
| 11 | +---@field hide? boolean @[default=true] If true, hide the subprocess console window that would normally be created. This option is only meaningful on Windows systems. On Unix it is silently ignored. | |
| 12 | +---@field uid? integer @[default=vim.uv.getuid()] Set the child process' user id. | |
| 13 | +---@field verbatim? boolean @[default=false] If true, do not wrap any arguments in quotes, or perform any other escaping, when converting the argument list into a command line string. This option is only meaningful on Windows systems. On Unix it is silently ignored. | |
| 14 | +---@field gid? integer @[default=vim.uv.getgid()] Set the child process' group id. | |
| 15 | +---The callback to run after the command has returned | |
| 16 | +---@field callback? fun(code:integer, signal:integer, handle:uv.uv_process_t, pid:integer) | |
| 17 | +---@field close? boolean @[default=true] Request the handle to be closed (to simplify callbacks) | |
| 18 | + | |
| 19 | +---A wrapper for uv.spawn that includes defaults. This makes it easier to spawn commands in the background. Also automatically closes the handle unless close is specified to false. | |
| 20 | +---@param path string the exectuable path | |
| 21 | +---@param p SpawnCommandParams | |
| 22 | +function M.spawn(path, p) | |
| 23 | + local args = p[2] | |
| 24 | + local stdio = p.stdio or { nil, nil, nil } | |
| 25 | + local cwd = p.cwd or vim.fn.getcwd() | |
| 26 | + local env = p.env or vim.fn.environ() | |
| 27 | + local detached = p.detatched ~= nil and p.detatched or true | |
| 28 | + local hide = p.hide ~= nil and p.hide or true | |
| 29 | + local uid = p.uid or vim.uv.getuid() | |
| 30 | + local verbatim = p.verbatim ~= nil and p.verbatim or false | |
| 31 | + local gid = p.gid ~= nil and p.gid or vim.uv.getgid() | |
| 32 | + local close = p.close ~= nil and p.close or true | |
| 33 | + | |
| 34 | + local handle, pid | |
| 35 | + handle, pid = vim.uv.spawn(path, { | |
| 36 | + args = args, | |
| 37 | + stdio = stdio, | |
| 38 | + cwd = cwd, | |
| 39 | + env = env, | |
| 40 | + detached = detached, | |
| 41 | + hide = hide, | |
| 42 | + ---@diagnostic disable-next-line: assign-type-mismatch | |
| 43 | + uid = uid, | |
| 44 | + verbatim = verbatim, | |
| 45 | + ---@diagnostic disable-next-line: assign-type-mismatch | |
| 46 | + gid = gid, | |
| 47 | + }, function(code, signal) | |
| 48 | + if p.callback then | |
| 49 | + p.callback(code, signal, handle, pid) | |
| 50 | + end | |
| 51 | + if close then | |
| 52 | + handle:close() | |
| 53 | + end | |
| 54 | + end) | |
| 55 | + return handle, pid | |
| 56 | +end | |
| 57 | + | |
| 58 | +return M |