1
0
mirror of https://github.com/SpaceVim/SpaceVim.git synced 2025-04-13 14:09:09 +08:00

feat(api): add lua job api

close https://github.com/neovim/neovim/issues/20856
This commit is contained in:
Eric Wong 2023-07-05 22:58:01 +08:00 committed by GitHub
parent d908e25959
commit 879129388a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 183 additions and 2 deletions

View File

@ -103,8 +103,7 @@ endfunction
function! s:on_update_exit(id, data, event) abort
" @bug on exit function is not called when failed
" C:\Users\wsdjeg\.SpaceVim>C:\Users\wsdjeg\.SpaceVim\bundle\phpcomplete.vim\bin\ctags.exe -R -o C:/Users/wsdjeg/.cache/SpaceVim/tags/C__Users_wsd
" jeg__SpaceVim_/tags C:\Users\wsdjeg\.SpaceVim
" C:\Users\wsdjeg\.SpaceVim>C:\Users\wsdjeg\.SpaceVim\bundle\phpcomplete.vim\bin\ctags.exe -R -o C:/Users/wsdjeg/.cache/SpaceVim/tags/C__Users_wsdjeg__SpaceVim_/tags C:\Users\wsdjeg\.SpaceVim
"
" C:\Users\wsdjeg\.SpaceVim>echo %ERRORLEVEL%
" -1073741819

159
lua/spacevim/api/job.lua Normal file
View File

@ -0,0 +1,159 @@
--=============================================================================
-- job.lua ---
-- Copyright (c) 2016-2022 Wang Shidong & Contributors
-- Author: Wang Shidong < wsdjeg@outlook.com >
-- URL: https://spacevim.org
-- License: GPLv3
--=============================================================================
local M = {}
local uv = vim.loop
local _jobs = {}
local _jobid = 0
local function new_job_obj(id, handle, opt, state)
local jobobj = {
id = id,
handle = handle,
opt = opt,
state = state,
}
return jobobj
end
function M.start(cmd, opts)
local stdin = uv.new_pipe()
local stdout = uv.new_pipe()
local stderr = uv.new_pipe()
local command = ''
local argv = {}
if type(cmd) == 'string' then
command = 'cmd.exe'
argv = { '/c', cmd }
elseif type(cmd) == 'table' then
command = cmd[1]
argv = vim.list_slice(cmd, 2)
end
local opt = {
stdio = { stdin, stdout, stderr },
args = argv,
}
_jobid = _jobid + 1
local current_id = _jobid
local exit_cb
if opts.on_exit then
exit_cb = function(code, singin)
opts.on_exit(current_id, code, singin)
end
end
local handle, pid = uv.spawn(command, opt, exit_cb)
_jobs['jobid_' .. _jobid] = new_job_obj(_jobid, handle, opts, {
stdout = stdout,
stderr = stderr,
stdin = stdin,
pid = pid,
})
if opts.on_stdout then
uv.read_start(stdout, function(err, data)
if data then
opts.on_stdout(current_id, data, 'stdout')
end
end)
end
if opts.on_stderr then
uv.read_start(stderr, function(err, data)
if data then
opts.on_stderr(current_id, data, 'stderr')
end
end)
end
return current_id
end
function M.send(id, data) -- {{{
local jobobj = _jobs['jobid_' .. id]
if not jobobj then
error('can not find job:' .. id)
end
local stdin = jobobj.state.stdin
if not stdin then
error('no stdin stream for jobid:' .. id)
end
if type(data) == 'table' then
for _, v in ipairs(data) do
stdin:write(v)
stdin:write('\n')
end
elseif type(data) == 'string' then
stdin:write(data)
elseif data == nil then
stdin:write('', function()
stdin:shutdown(function()
if stdin then
stdin:close()
end
end)
end)
end
end
function M.chanclose(id, t)
local jobobj = _jobs['jobid_' .. id]
if not jobobj then
error('can not find job:' .. id)
end
if t == 'stdin' then
local stdin = jobobj.state.stdin
if not stdin then
stdin:shutdown(function()
if stdin then
stdin:close()
end
end)
end
elseif t == 'stdout' then
elseif t == 'stderr' then
else
error('the type only can be:stdout, stdin or stderr')
end
end
function M.stop(id)
local jobobj = _jobs['jobid_' .. id]
if not jobobj then
error('can not find job:' .. id)
end
-- close stdio
local stdin = jobobj.state.stdin
if stdin and stdin:is_active() then
stdin:close()
end
-- close stdio
local stdout = jobobj.state.stout
if stdout and stdout:is_active() then
stdout:close()
end
-- close stdio
local stderr = jobobj.state.stderr
if stderr and stderr:is_active() then
stderr:close()
end
local handle = jobobj.handle
handle:kill(6)
end
return M

23
test/lua/test_job.lua Normal file
View File

@ -0,0 +1,23 @@
local job = require('spacevim.api.job')
local jobid = job.start({ 'rg', 'wsdjeg', '.' }, {
on_stdout = function(id, data, event)
vim.print(id)
vim.print(data)
vim.print(event)
end,
on_stderr = function(id, data, event)
vim.print(id)
vim.print(data)
vim.print(event)
end,
on_exit = function(id, code, signal)
vim.print(id)
vim.print('exit code', code)
vim.print('exit signal', signal)
end,
})
-- job.send(jobid, 'hello world')
-- job.stop(jobid)