Skip to content

Commit f48f117

Browse files
authored
refactor(cli, nvim): add exit code to job runners.
2 parents f859252 + 7ec5e71 commit f48f117

9 files changed

Lines changed: 213 additions & 162 deletions

File tree

lua/vectorcode/cacher/default.lua

Lines changed: 34 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
local M = {}
33
local vc_config = require("vectorcode.config")
44
local notify_opts = vc_config.notify_opts
5+
local jobrunner = require("vectorcode.jobrunner.cmd")
56

67
local logger = vc_config.logger
78

@@ -58,37 +59,35 @@ local function async_runner(query_message, buf_nr)
5859
)
5960
vim.list_extend(args, { "--project_root", project_root })
6061
end
62+
63+
if cache.options.single_job then
64+
kill_jobs(buf_nr)
65+
end
66+
6167
CACHE[buf_nr].job_count = CACHE[buf_nr].job_count + 1
6268
logger.debug("vectorcode default cacher job args: ", args)
63-
local job = require("plenary.job"):new({
64-
command = "vectorcode",
65-
args = args,
66-
detached = true,
67-
on_start = function()
68-
if cache.options.single_job then
69-
kill_jobs(buf_nr)
70-
end
71-
end,
72-
on_exit = function(self, code, signal)
69+
70+
-- jobrunner is assumed to be defined at the module level, e.g., local jobrunner = require("vectorcode.jobrunner.cmd")
71+
local job_pid
72+
job_pid = jobrunner.run_async(
73+
args,
74+
function(json_result, stderr_error, exit_code, signal)
7375
if not M.buf_is_registered(buf_nr) then
7476
return
7577
end
76-
logger.debug("vectorcode ", buf_name, " default cacher results: ", self:result())
78+
logger.debug("vectorcode ", buf_name, " default cacher results: ", json_result)
7779
CACHE[buf_nr].job_count = CACHE[buf_nr].job_count - 1
78-
CACHE[buf_nr].jobs[self.pid] = nil
79-
local ok, json = pcall(
80-
vim.json.decode,
81-
table.concat(self:result()) or "[]",
82-
{ array = true, object = true }
83-
)
84-
if not ok or code ~= 0 then
80+
assert(job_pid ~= nil)
81+
CACHE[buf_nr].jobs[job_pid] = nil
82+
83+
if exit_code ~= 0 then
8584
vim.schedule(function()
8685
if CACHE[buf_nr].options.notify then
8786
if signal == 15 then
8887
vim.notify("Retrieval aborted.", vim.log.levels.INFO, notify_opts)
8988
else
9089
vim.notify(
91-
"Retrieval failed:\n" .. table.concat(self:result()),
90+
"Retrieval failed:\\n" .. table.concat(stderr_error, "\n"),
9291
vim.log.levels.WARN,
9392
notify_opts
9493
)
@@ -98,7 +97,7 @@ local function async_runner(query_message, buf_nr)
9897
return
9998
end
10099
cache = CACHE[buf_nr]
101-
cache.retrieval = json or {}
100+
cache.retrieval = json_result or {}
102101
vim.schedule(function()
103102
if cache.options.notify then
104103
vim.notify(
@@ -109,12 +108,15 @@ local function async_runner(query_message, buf_nr)
109108
end
110109
end)
111110
end,
112-
})
113-
job:start()
111+
buf_nr
112+
)
113+
114114
---@type VectorCode.Cache
115115
cache = CACHE[buf_nr]
116-
cache.last_run = vim.uv.clock_gettime("realtime").sec
117-
cache.jobs[job.pid] = vim.uv.clock_gettime("realtime").sec
116+
if job_pid then
117+
cache.last_run = vim.uv.clock_gettime("realtime").sec
118+
cache.jobs[job_pid] = vim.uv.clock_gettime("realtime").sec
119+
end
118120
vim.schedule(function()
119121
if cache.options.notify then
120122
vim.notify(
@@ -313,21 +315,14 @@ end
313315
---@param on_success fun(out: vim.SystemCompleted)?
314316
---@param on_failure fun(out: vim.SystemCompleted?)?
315317
function M.async_check(check_item, on_success, on_failure)
316-
if not vc_config.has_cli() then
317-
if on_failure ~= nil then
318-
on_failure()
319-
end
320-
return
321-
end
322-
323-
check_item = check_item or "config"
324-
vim.system({ "vectorcode", "check", check_item }, {}, function(out)
325-
if out.code == 0 and type(on_success) == "function" then
326-
vim.schedule_wrap(on_success)(out)
327-
elseif out.code ~= 0 and type(on_failure) == "function" then
328-
vim.schedule_wrap(on_failure)(out)
329-
end
330-
end)
318+
vim.deprecate(
319+
"vectorcode.cacher.default.async_check",
320+
"vectorcode.cacher.utils.async_check",
321+
"0.7.0",
322+
"VectorCode",
323+
true
324+
)
325+
require("vectorcode.cacher").utils.async_check(check_item, on_success, on_failure)
331326
end
332327

333328
---@param bufnr integer?

lua/vectorcode/cacher/init.lua

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,36 @@
1+
local vc_config = require("vectorcode.config")
2+
local jobrunner = require("vectorcode.jobrunner.cmd")
3+
14
return {
25
lsp = require("vectorcode.cacher.lsp"),
36
default = require("vectorcode.cacher.default"),
7+
utils = {
8+
---Checks if VectorCode has been configured properly for your project.
9+
---See the CLI manual for details.
10+
---@param check_item string?
11+
---@param on_success fun(out: vim.SystemCompleted)?
12+
---@param on_failure fun(out: vim.SystemCompleted?)?
13+
async_check = function(check_item, on_success, on_failure)
14+
if not vc_config.has_cli() then
15+
if on_failure ~= nil then
16+
on_failure()
17+
end
18+
return
19+
end
20+
check_item = check_item or "config"
21+
jobrunner.run_async({ "check", check_item }, function(result, error, code, signal)
22+
local out = {
23+
stdout = table.concat(vim.iter(result):flatten(math.huge):totable()),
24+
stderr = table.concat(vim.iter(error):flatten(math.huge):totable()),
25+
code = code,
26+
signal = signal,
27+
}
28+
if out.code == 0 and type(on_success) == "function" then
29+
vim.schedule_wrap(on_success)(out)
30+
elseif out.code ~= 0 and type(on_failure) == "function" then
31+
vim.schedule_wrap(on_failure)(out)
32+
end
33+
end, 0)
34+
end,
35+
},
436
}

lua/vectorcode/cacher/lsp.lua

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -348,21 +348,14 @@ end
348348
---@param on_success fun(out: vim.SystemCompleted)?
349349
---@param on_failure fun(out: vim.SystemCompleted?)?
350350
function M.async_check(check_item, on_success, on_failure)
351-
if not vc_config.has_cli() then
352-
if on_failure ~= nil then
353-
on_failure()
354-
end
355-
return
356-
end
357-
358-
check_item = check_item or "config"
359-
vim.system({ "vectorcode", "check", check_item }, {}, function(out)
360-
if out.code == 0 and type(on_success) == "function" then
361-
vim.schedule_wrap(on_success)(out)
362-
elseif out.code ~= 0 and type(on_failure) == "function" then
363-
vim.schedule_wrap(on_failure)(out)
364-
end
365-
end)
351+
vim.deprecate(
352+
"vectorcode.cacher.default.async_check",
353+
"vectorcode.cacher.utils.async_check",
354+
"0.7.0",
355+
"VectorCode",
356+
true
357+
)
358+
require("vectorcode.cacher").utils.async_check(check_item, on_success, on_failure)
366359
end
367360

368361
---@param bufnr integer?

lua/vectorcode/init.lua

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -186,14 +186,17 @@ function M.check(check_item, stdout_cb)
186186
end
187187
check_item = check_item or "config"
188188
local return_code
189-
vim
190-
.system({ "vectorcode", "check", check_item }, {}, function(out)
191-
return_code = out.code
192-
if type(stdout_cb) == "function" then
193-
stdout_cb(out)
194-
end
195-
end)
196-
:wait()
189+
jobrunner.run_async({ "check", check_item }, function(result, error, code, signal)
190+
return_code = code
191+
if type(stdout_cb) == "function" then
192+
stdout_cb({
193+
stdout = table.concat(vim.iter(result):flatten(math.huge):totable()),
194+
stderr = table.concat(vim.iter(error):flatten(math.huge):totable()),
195+
code = code,
196+
signal = signal,
197+
})
198+
end
199+
end, 0)
197200
return return_code == 0
198201
end
199202

lua/vectorcode/jobrunner/cmd.lua

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,14 @@ function runner.run_async(args, callback, bufnr)
2222
local job = Job:new({
2323
command = "vectorcode",
2424
args = args,
25-
on_exit = function(self, _, _)
25+
on_exit = function(self, code, signal)
2626
jobs[self.pid] = nil
2727
local result = self:result()
2828
logger.debug(result)
2929
local ok, decoded = pcall(vim.json.decode, table.concat(result, ""))
3030
if callback ~= nil then
3131
if ok then
32-
callback(decoded or {}, self:stderr_result())
32+
callback(decoded or {}, self:stderr_result(), code, signal)
3333
if vim.islist(result) then
3434
logger.debug(
3535
"cmd jobrunner result:\n",
@@ -43,7 +43,7 @@ function runner.run_async(args, callback, bufnr)
4343
)
4444
end
4545
else
46-
callback({ result }, self:stderr_result())
46+
callback({ result }, self:stderr_result(), code, signal)
4747
logger.warn("cmd runner: failed to decode result:\n", result)
4848
end
4949
end
@@ -58,20 +58,20 @@ function runner.run(args, timeout_ms, bufnr)
5858
if timeout_ms == nil or timeout_ms < 0 then
5959
timeout_ms = 2 ^ 31 - 1
6060
end
61-
local res, err
62-
local pid = runner.run_async(args, function(result, error)
61+
local res, err, code, signal
62+
local pid = runner.run_async(args, function(result, error, e_code, s)
6363
res = result
6464
err = error
65+
code = e_code
66+
signal = s
6567
end, bufnr)
6668
if pid ~= nil then
6769
vim.wait(timeout_ms, function()
6870
return res ~= nil or err ~= nil
6971
end)
7072
jobs[pid] = nil
71-
return res, err
72-
else
73-
return {}, err
7473
end
74+
return res or {}, err, code, signal
7575
end
7676

7777
function runner.is_job_running(job)

lua/vectorcode/jobrunner/init.lua

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,23 @@ local utils = require("vectorcode.utils")
66
---@class VectorCode.JobRunner
77
--- Runs a vectorcode command asynchronously.
88
--- Executes the command specified by `args`. Upon completion, if `callback` is provided,
9-
--- it's invoked with the result table (decoded JSON from stdout) and error table (stderr lines).
9+
--- it's invoked with the following arguments:
10+
--- - `result`: the JSON object of the command execution result.
11+
--- - `error`: error messages, if any.
12+
--- - `code`: exit code (or error code) for the process.
13+
--- - `signal`: _for cmd runner only_, the shell signal sent to the process.
1014
--- The `bufnr` is used for context, potentially to find the project root or attach LSP clients.
1115
--- Returns a job handle (e.g., PID or LSP request ID) or nil if the job couldn't be started.
12-
---@field run_async fun(args: string[], callback:fun(result: table, error: table)?, bufnr: integer):(job_handle:integer?)
16+
---@field run_async fun(args: string[], callback:fun(result: table, error: table, code:integer, signal: integer?)?, bufnr: integer):(job_handle:integer?)
1317
--- Runs a vectorcode command synchronously, blocking until completion or timeout.
1418
--- Executes the command specified by `args`. Waits for up to `timeout_ms` milliseconds.
1519
--- The `bufnr` is used for context, potentially to find the project root or attach LSP clients.
16-
--- Returns the result table (decoded JSON from stdout) and error table (stderr lines).
17-
---@field run fun(args: string[], timeout_ms: integer?, bufnr: integer):(result:table, error:table)
20+
--- Returns the following objects:
21+
--- - `result`: the JSON object of the command execution result.
22+
--- - `error`: error messages, if any.
23+
--- - `code`: exit code (or error code) for the process.
24+
--- - `signal`: _for cmd runner only_, the shell signal sent to the process.
25+
---@field run fun(args: string[], timeout_ms: integer?, bufnr: integer):(result:table, error:table, code:integer, signal: integer?)
1826
--- Checks if a job associated with the given handle is currently running.
1927
--- Returns true if the job is running, false otherwise.
2028
---@field is_job_running fun(job_handle: integer):boolean

lua/vectorcode/jobrunner/lsp.lua

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -52,18 +52,16 @@ function jobrunner.run(args, timeout_ms, bufnr)
5252
end
5353
args = require("vectorcode.jobrunner").find_root(args, bufnr)
5454

55-
local result, err
56-
jobrunner.run_async(args, function(res, err)
55+
local result, err, code
56+
jobrunner.run_async(args, function(res, err, e_code)
5757
result = res
5858
err = err
59+
code = e_code
5960
end, bufnr)
6061
vim.wait(timeout_ms, function()
6162
return (result ~= nil) or (err ~= nil)
6263
end)
63-
if result == nil then
64-
return {}, err
65-
end
66-
return result, err
64+
return result or {}, err, code
6765
end
6866

6967
function jobrunner.run_async(args, callback, bufnr)
@@ -102,7 +100,11 @@ function jobrunner.run_async(args, callback, bufnr)
102100
if err ~= nil and err.message ~= nil then
103101
err_message = { err.message }
104102
end
105-
vim.schedule_wrap(callback)(result, err_message)
103+
local code = 0
104+
if err and err.code then
105+
code = err.code
106+
end
107+
vim.schedule_wrap(callback)(result, err_message, code)
106108
if result then
107109
logger.debug(
108110
"lsp jobrunner result:\n",

0 commit comments

Comments
 (0)