mirror of
https://github.com/zoriya/jj.nvim.git
synced 2026-08-15 23:53:18 +00:00
refactor!: Migrate runners cmd from string to argv (#134)
Migrate command execution to structured argv lists across the plugin, replacing shell-string command construction with `vim.system` argv execution. The runner API now exposes argv-based execution as the default path:
- `runner.execute_command` -> `runner.execute`
- `runner.execute_command_async` -> `runner.execute_async`
- `runner.execute_command_raw` -> `runner.execute_raw`
- `runner.execute_command_raw_async` -> `runner.execute_raw_async`
- `runner.execute_command_sync` was removed; use `runner.execute` and handle the result directly
BREAKING CHANGES:
- `cmd.new({ args = ... })` now requires `args` as `string[]` argv tokens, not a single string.
- `cmd.log({ ... })` now uses `raw_flags` as `string[]` for raw passthrough flags; `raw = "..."` is no longer supported.
- Direct users of `jj.core.runner` must migrate from the old `execute_command*` string helpers to the new argv-based `execute*` helpers.
This commit is contained in:
+45
-87
@@ -8,122 +8,80 @@ local function error_notify(msg, error_prefix, silent)
|
||||
end
|
||||
end
|
||||
|
||||
--- Execute a system command and return output with error handling
|
||||
--- @param cmd string The command to execute
|
||||
--- @param error_prefix string|nil Optional error message prefix
|
||||
--- @param input string|nil Optional input to pass to stdin
|
||||
--- @param silent boolean|nil Optional to silent the notification
|
||||
--- Execute a system command with arguments and return output with error handling
|
||||
---@param argv string[] The command and its arguments to execute
|
||||
---@param error_prefix string|nil
|
||||
---@param input string|nil
|
||||
---@param silent boolean|nil
|
||||
--- @return string|nil output The command output, or nil if failed
|
||||
--- @return boolean success Whether the command succeeded
|
||||
function M.execute_command(cmd, error_prefix, input, silent)
|
||||
local stderr_file = vim.fn.tempname()
|
||||
local output =
|
||||
vim.fn.system({ "sh", "-c", string.format("(%s) 2>%s", cmd, vim.fn.shellescape(stderr_file)) }, input)
|
||||
local success = vim.v.shell_error == 0
|
||||
function M.execute(argv, error_prefix, input, silent)
|
||||
local result = vim.system(argv, { stdin = input, text = true }):wait()
|
||||
|
||||
if not success then
|
||||
local stderr_lines = vim.fn.readfile(stderr_file)
|
||||
vim.fn.delete(stderr_file)
|
||||
local error_output = table.concat(stderr_lines, "\n")
|
||||
local msg = error_output ~= "" and error_output or output
|
||||
error_notify(msg, error_prefix, silent)
|
||||
return nil, false
|
||||
end
|
||||
|
||||
vim.fn.delete(stderr_file)
|
||||
return output, success
|
||||
end
|
||||
|
||||
--- Execute a system command and return its raw stdout bytes.
|
||||
--- Skips replacement of NUL bytes with SOH (0x01),
|
||||
--- which corrupts UTF-16 and other binary-ish content.
|
||||
--- @param cmd string The command to execute
|
||||
--- @param error_prefix string|nil Optional error message prefix
|
||||
--- @param silent boolean|nil Optional to silent the notification
|
||||
--- @return string|nil output Raw stdout bytes, or nil if failed
|
||||
--- @return boolean success Whether the command succeeded
|
||||
--- @return string stderr The command's stderr (empty on success)
|
||||
function M.execute_command_raw(cmd, error_prefix, silent)
|
||||
local result = vim.system({ "sh", "-c", cmd }):wait()
|
||||
if result.code ~= 0 then
|
||||
local msg = result.stderr ~= "" and result.stderr or result.stdout or ""
|
||||
error_notify(msg, error_prefix, silent)
|
||||
return nil, false, msg
|
||||
return nil, false
|
||||
end
|
||||
return result.stdout or "", true, ""
|
||||
return result.stdout or "", true
|
||||
end
|
||||
|
||||
--- Execute a system command synchronously and call success callback.
|
||||
--- @param cmd string The command to execute
|
||||
--- Execute an argv command with arguments asynchronously and call success callback.
|
||||
--- @param argv string[] The command and its arguments to execute
|
||||
--- @param on_success function|nil Callback on success, receives output as parameter
|
||||
--- @param error_prefix string|nil Optional error message prefix
|
||||
--- @param input string|nil Optional input to pass to stdin
|
||||
--- @param silent boolean|nil Optional to silent the notification
|
||||
--- @return string|nil output The command output, or nil if failed
|
||||
--- @return boolean success Whether the command succeeded
|
||||
function M.execute_command_sync(cmd, on_success, error_prefix, input, silent)
|
||||
local output, success = M.execute_command(cmd, error_prefix, input, silent)
|
||||
if success and on_success then
|
||||
on_success(output)
|
||||
end
|
||||
return output, success
|
||||
end
|
||||
|
||||
--- Execute a system command asynchronously
|
||||
--- @param cmd string The command to execute
|
||||
--- @param on_success function|nil Callback on success, receives output as parameter
|
||||
--- @param error_prefix string|nil Optional error message prefix
|
||||
--- @param input string|nil Optional input to pass to stdin
|
||||
--- @param silent boolean|nil Optional to silent the notification
|
||||
--- @param on_error function|nil Callback on error, receives ouptut as the parameter
|
||||
function M.execute_command_async(cmd, on_success, error_prefix, input, silent, on_error)
|
||||
local stdout_lines = {}
|
||||
local stderr_lines = {}
|
||||
|
||||
local job_id = vim.fn.jobstart({ "sh", "-c", cmd }, {
|
||||
stdout_buffered = true,
|
||||
stderr_buffered = true,
|
||||
on_stdout = function(_, data)
|
||||
vim.list_extend(stdout_lines, data)
|
||||
end,
|
||||
on_stderr = function(_, data)
|
||||
vim.list_extend(stderr_lines, data)
|
||||
end,
|
||||
on_exit = function(_, exit_code)
|
||||
local output = table.concat(stdout_lines, "\n")
|
||||
if exit_code == 0 then
|
||||
--- @param on_error function|nil Callback on error, receives the error message
|
||||
function M.execute_async(argv, on_success, error_prefix, input, silent, on_error)
|
||||
vim.system(
|
||||
argv,
|
||||
{ stdin = input, text = true },
|
||||
vim.schedule_wrap(function(res)
|
||||
if res.code == 0 then
|
||||
if on_success then
|
||||
on_success(output)
|
||||
on_success(res.stdout or "")
|
||||
end
|
||||
else
|
||||
local error_output = table.concat(stderr_lines, "\n")
|
||||
local msg = error_output ~= "" and error_output or output
|
||||
local msg = res.stderr ~= "" and res.stderr or res.stdout or ""
|
||||
error_notify(msg, error_prefix, silent)
|
||||
if on_error then
|
||||
on_error(msg)
|
||||
end
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
-- Send stdin if provided
|
||||
if input then
|
||||
vim.fn.chansend(job_id, input)
|
||||
vim.fn.chanclose(job_id, "stdin")
|
||||
end
|
||||
end)
|
||||
)
|
||||
end
|
||||
|
||||
--- Execute a system command asynchronously and receive raw stdout bytes.
|
||||
--- Execute an argv command with arguments and return raw stdout bytes.
|
||||
--- Skips replacement of NUL bytes with SOH (0x01).
|
||||
--- @param cmd string The command to execute
|
||||
--- @param argv string[] The command and its arguments to execute
|
||||
--- @param error_prefix string|nil Optional error message prefix
|
||||
--- @param silent boolean|nil Optional to silent the notification
|
||||
--- @return string|nil output Raw stdout bytes, or nil if failed
|
||||
--- @return boolean success Whether the command succeeded
|
||||
--- @return string stderr The command's stderr (empty on success)
|
||||
function M.execute_raw(argv, error_prefix, silent)
|
||||
local result = vim.system(argv, { text = false }):wait()
|
||||
if result.code ~= 0 then
|
||||
local msg = result.stderr ~= "" and result.stderr or result.stdout or ""
|
||||
error_notify(msg, error_prefix, silent)
|
||||
return nil, false, msg
|
||||
end
|
||||
return result.stdout or "", true, result.stderr or ""
|
||||
end
|
||||
|
||||
--- Execute an argv command with arguments asynchronously and receive raw stdout bytes.
|
||||
--- Skips replacement of NUL bytes with SOH (0x01).
|
||||
--- @param argv string[] The command and its arguments to execute
|
||||
--- @param on_success function|nil Callback on success, receives raw stdout bytes
|
||||
--- @param error_prefix string|nil Optional error message prefix
|
||||
--- @param silent boolean|nil Optional to silent the notification
|
||||
--- @param on_error function|nil Callback on error, receives the error message
|
||||
function M.execute_command_raw_async(cmd, on_success, error_prefix, silent, on_error)
|
||||
function M.execute_raw_async(argv, on_success, error_prefix, silent, on_error)
|
||||
vim.system(
|
||||
{ "sh", "-c", cmd },
|
||||
{},
|
||||
argv,
|
||||
{ text = false },
|
||||
vim.schedule_wrap(function(res)
|
||||
if res.code == 0 then
|
||||
if on_success then
|
||||
|
||||
Reference in New Issue
Block a user