go.nvim/lua/go/runner.lua

205 lines
5.4 KiB
Lua
Raw Normal View History

2021-03-10 12:15:06 +00:00
local uv, api = vim.loop, vim.api
2022-07-30 13:05:27 +00:00
local util = require('go.utils')
local log = require('go.utils').log
2021-03-10 12:15:06 +00:00
-- run command with loop
local run = function(cmd, opts, uvopts)
uvopts = uvopts or {}
2021-09-03 02:13:15 +00:00
opts = opts or {}
log(cmd)
2022-07-30 13:05:27 +00:00
if type(cmd) == 'string' then
local split_pattern = '%s+'
2021-09-03 02:13:15 +00:00
cmd = vim.split(cmd, split_pattern)
log(cmd)
end
2022-02-02 04:49:54 +00:00
local cmd_str = vim.inspect(cmd)
2021-09-03 02:13:15 +00:00
local job_options = vim.deepcopy(opts or {})
job_options.args = job_options.args or {}
local cmdargs = vim.list_slice(cmd, 2, #cmd) or {}
2021-11-13 03:29:42 +00:00
2022-07-30 13:05:27 +00:00
if cmdargs and cmdargs[1] == 'test' and #cmdargs == 3 then
table.insert(cmdargs, '.' .. util.sep() .. '...')
2021-11-13 03:29:42 +00:00
log(cmdargs)
end
2021-09-03 02:13:15 +00:00
vim.list_extend(cmdargs, job_options.args)
job_options.args = cmdargs
cmd = cmd[1]
log(cmd, job_options.args)
2021-03-10 12:15:06 +00:00
local stdin = uv.new_pipe(false)
local stdout = uv.new_pipe(false)
local stderr = uv.new_pipe(false)
2021-09-03 02:13:15 +00:00
-- local file = api.nvim_buf_get_name(0)
local handle = nil
2021-03-10 12:15:06 +00:00
2022-07-30 13:05:27 +00:00
local output_buf = ''
2022-08-06 12:00:49 +00:00
local output_stderr = ''
local function update_chunk_fn(err, chunk)
2022-06-01 11:29:13 +00:00
if err then
2022-07-05 22:28:29 +00:00
vim.schedule(function()
util.error('error ' .. tostring(err) .. vim.inspect(chunk or ''), vim.log.levels.WARN)
2022-07-05 22:28:29 +00:00
end)
2022-06-01 11:29:13 +00:00
end
2022-10-06 04:16:29 +00:00
local lines = {}
2021-09-03 02:13:15 +00:00
if chunk then
for s in chunk:gmatch('[^\r\n]+') do
table.insert(lines, s)
end
2022-12-14 20:11:08 +00:00
output_buf = output_buf .. '\n' .. table.concat(lines, '\n')
log(lines)
2023-02-24 07:42:11 +00:00
local cfixlines = vim.split(output_buf, '\n')
local locopts = {
title = vim.inspect(cmd),
lines = cfixlines,
}
if opts.efm then
locopts.efm = opts.efm
end
log(locopts)
vim.schedule(function()
vim.fn.setloclist(0, {}, 'r', locopts)
vim.notify('run lopen to see output', vim.log.levels.INFO)
end)
2021-03-10 12:15:06 +00:00
end
2022-10-06 04:16:29 +00:00
return lines
end
local update_chunk = function(err, chunk)
local lines
if opts.update_chunk then
lines = opts.update_chunk(err, chunk)
else
lines = update_chunk_fn(err, chunk)
end
if opts.on_chunk and lines then
opts.on_chunk(err, lines)
end
_GO_NVIM_CFG.on_stdout(err, chunk)
2021-09-03 02:13:15 +00:00
end
2022-07-30 13:05:27 +00:00
log('job:', cmd, job_options)
local Sprite = util.load_plugin('guihua.lua', 'guihua.sprite')
local sprite
if Sprite then
sprite = Sprite:new({
loc = 'top_center',
syntax = 'lua',
2023-02-24 07:42:11 +00:00
rect = { height = 1, width = 30 },
data = { 'Running ' .. vim.inspect(cmd) },
timeout = 30000,
hl_line = 1,
})
else
2023-02-24 07:42:11 +00:00
sprite = { on_close = function() end }
end
if uvopts.cwd then
log('cwd', opts.cwd)
if uvopts.cwd == '%:h' then
uvopts.cwd = vim.fn.expand(opts.cwd)
end
else
if vim.fn.expand('%:t'):find('go.mod') or vim.fn.expand('%:t'):find('go.work') then
opts.cwd = vim.fn.expand('%:p:h')
end
end
output_buf = ''
output_stderr = ''
2022-06-01 11:29:13 +00:00
handle, _ = uv.spawn(
2022-02-02 04:49:54 +00:00
cmd,
{ stdio = { stdin, stdout, stderr }, cwd = uvopts.cwd, args = job_options.args },
function(code, signal) -- on exit()
2022-02-02 04:49:54 +00:00
stdin:close()
2021-09-03 02:13:15 +00:00
2022-02-02 04:49:54 +00:00
stdout:read_stop()
stdout:close()
stderr:read_stop()
stderr:close()
2022-02-02 04:49:54 +00:00
handle:close()
2023-02-24 07:42:11 +00:00
log('spawn finished', code, signal)
sprite.on_close()
2022-08-06 12:00:49 +00:00
if output_stderr ~= '' then
2022-08-06 12:00:49 +00:00
vim.schedule(function()
vim.notify(output_stderr)
end)
end
2022-07-05 22:28:29 +00:00
if code ~= 0 then
2022-07-30 13:05:27 +00:00
log('failed to run', code, output_buf)
2023-02-24 07:42:11 +00:00
vim.schedule(function()
util.error( cmd_str .. ' failed exit code ' .. tostring(code or 0) .. (output_buf or ''))
end)
2022-07-05 22:28:29 +00:00
end
2023-02-24 07:42:11 +00:00
local combine_output = ''
2023-02-24 07:42:11 +00:00
if output_buf ~= '' or output_stderr ~= '' then
-- some commands may output to stderr instead of stdout
combine_output = (output_buf or '') .. '\n' .. (output_stderr or '')
combine_output = util.remove_ansi_escape(combine_output)
combine_output = vim.trim(combine_output)
end
if opts and opts.on_exit then
local onexit_output = opts.on_exit(code, signal, combine_output)
if not onexit_output then
return
else
combine_output = onexit_output
end
end
if code ~= 0 or signal ~= 0 or output_stderr ~= '' then
local lines = util.handle_job_data(vim.split(combine_output, '\n'))
2022-07-05 22:28:29 +00:00
local locopts = {
title = vim.inspect(cmd),
lines = lines,
}
if opts.efm then
locopts.efm = opts.efm
end
log('command finished: ', locopts, lines)
2022-07-05 22:28:29 +00:00
if #lines > 0 then
vim.schedule(function()
2022-07-30 13:05:27 +00:00
vim.fn.setloclist(0, {}, ' ', locopts)
util.info('run lopen to see output')
2022-07-05 22:28:29 +00:00
end)
2022-06-28 05:35:05 +00:00
end
2022-02-21 22:46:59 +00:00
end
_GO_NVIM_CFG.on_exit(code, signal, output_buf)
2022-02-02 04:49:54 +00:00
end
)
_GO_NVIM_CFG.on_jobstart(cmd)
2021-09-03 02:13:15 +00:00
uv.read_start(stderr, function(err, data)
2022-08-06 12:00:49 +00:00
if err then
util.error(tostring(err) .. tostring(data or ''))
2022-08-06 12:00:49 +00:00
end
if data ~= nil then
log('stderr read handler', data)
output_stderr = output_stderr .. util.remove_ansi_escape(tostring(data))
end
_GO_NVIM_CFG.on_stderr(err, data)
2021-09-03 02:13:15 +00:00
end)
stdout:read_start(update_chunk)
2022-08-04 13:30:52 +00:00
return stdin, stdout, stderr
2021-09-03 02:13:15 +00:00
end
2021-03-10 12:15:06 +00:00
2021-09-03 02:13:15 +00:00
local function make(...)
2022-07-30 13:05:27 +00:00
local makeprg = vim.api.nvim_buf_get_option(0, 'makeprg')
2022-02-02 04:49:54 +00:00
local args = { ... }
2021-11-13 03:29:42 +00:00
local setup = {}
2021-09-03 02:13:15 +00:00
if #args > 0 then
2022-06-01 11:29:13 +00:00
for _, v in ipairs(args) do
2021-09-03 02:13:15 +00:00
table.insert(setup, v)
2021-03-10 12:15:06 +00:00
end
2021-09-03 02:13:15 +00:00
end
local opts = {}
opts.args = setup
run(makeprg, opts)
2021-03-10 12:15:06 +00:00
end
2022-02-02 04:49:54 +00:00
return { run = run, make = make }