Files
Nicolas GBandGitHub 7f2786ff16 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.
2026-07-07 18:25:30 +02:00

102 lines
3.6 KiB
Lua

--- @class jj.core.runner
local M = {}
local function error_notify(msg, error_prefix, silent)
local error_message = error_prefix and string.format("%s: %s", error_prefix, msg) or msg
if not silent then
vim.notify(error_message, vim.log.levels.ERROR, { title = "JJ" })
end
end
--- 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(argv, error_prefix, input, silent)
local result = vim.system(argv, { stdin = input, text = true }):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
end
return result.stdout or "", true
end
--- 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
--- @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(res.stdout or "")
end
else
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)
)
end
--- Execute an argv command with arguments and return raw stdout bytes.
--- Skips replacement of NUL bytes with SOH (0x01).
--- @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_raw_async(argv, on_success, error_prefix, silent, on_error)
vim.system(
argv,
{ text = false },
vim.schedule_wrap(function(res)
if res.code == 0 then
if on_success then
on_success(res.stdout or "")
end
else
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)
)
end
return M