119 lines
2.9 KiB
Lua
119 lines
2.9 KiB
Lua
local M = {}
|
|
|
|
-- Find the shout binary: prefer local node_modules, then PATH
|
|
local function shout_cmd()
|
|
local local_bin = vim.fn.findfile("node_modules/.bin/shout", vim.fn.getcwd() .. ";")
|
|
if local_bin ~= "" then
|
|
return vim.fn.fnamemodify(local_bin, ":p")
|
|
end
|
|
-- Try bun run
|
|
if vim.fn.executable("bun") == 1 then
|
|
return "bun run shout"
|
|
end
|
|
return "shout"
|
|
end
|
|
|
|
-- Parse shout test output for quickfix entries
|
|
local function parse_output(lines, file)
|
|
local items = {}
|
|
for _, line in ipairs(lines) do
|
|
-- Match "FAIL path" lines
|
|
local fail_path = line:match("^FAIL%s+(.+)$")
|
|
if fail_path then
|
|
table.insert(items, {
|
|
filename = fail_path,
|
|
lnum = 1,
|
|
text = "FAIL",
|
|
type = "E",
|
|
})
|
|
end
|
|
-- Match " $ command" lines after a FAIL (command that failed)
|
|
local cmd = line:match("^%s+%$%s+(.+)$")
|
|
if cmd then
|
|
table.insert(items, {
|
|
filename = file or "",
|
|
lnum = 0,
|
|
text = "$ " .. cmd,
|
|
type = "I",
|
|
})
|
|
end
|
|
end
|
|
return items
|
|
end
|
|
|
|
local function run_shout(args, on_exit)
|
|
local cmd = shout_cmd() .. " test " .. args
|
|
local output_lines = {}
|
|
|
|
vim.fn.jobstart(cmd, {
|
|
stdout_buffered = true,
|
|
stderr_buffered = true,
|
|
on_stdout = function(_, data)
|
|
vim.list_extend(output_lines, data)
|
|
end,
|
|
on_stderr = function(_, data)
|
|
vim.list_extend(output_lines, data)
|
|
end,
|
|
on_exit = function(_, code)
|
|
vim.schedule(function()
|
|
if on_exit then
|
|
on_exit(code, output_lines)
|
|
end
|
|
end)
|
|
end,
|
|
})
|
|
end
|
|
|
|
local ns = vim.api.nvim_create_namespace("shout")
|
|
|
|
local function show_results(code, lines, file)
|
|
-- Clear previous diagnostics
|
|
if file then
|
|
local bufnr = vim.fn.bufnr(file)
|
|
if bufnr ~= -1 then
|
|
vim.diagnostic.reset(ns, bufnr)
|
|
end
|
|
end
|
|
|
|
-- Show in quickfix
|
|
local items = parse_output(lines, file)
|
|
vim.fn.setqflist(items, "r")
|
|
|
|
if code == 0 then
|
|
vim.notify("shout: all tests passed", vim.log.levels.INFO)
|
|
else
|
|
vim.notify("shout: tests failed (see :copen)", vim.log.levels.ERROR)
|
|
vim.cmd("copen")
|
|
end
|
|
end
|
|
|
|
function M.run()
|
|
local file = vim.fn.expand("%:p")
|
|
vim.notify("shout: running " .. vim.fn.expand("%:t") .. "...", vim.log.levels.INFO)
|
|
run_shout(vim.fn.shellescape(file), function(code, lines)
|
|
show_results(code, lines, file)
|
|
end)
|
|
end
|
|
|
|
function M.update()
|
|
local file = vim.fn.expand("%:p")
|
|
vim.notify("shout: updating " .. vim.fn.expand("%:t") .. "...", vim.log.levels.INFO)
|
|
run_shout("--update " .. vim.fn.shellescape(file), function(code, lines)
|
|
if code == 0 then
|
|
vim.cmd("edit") -- reload the buffer
|
|
vim.notify("shout: updated " .. vim.fn.expand("%:t"), vim.log.levels.INFO)
|
|
else
|
|
show_results(code, lines, file)
|
|
end
|
|
end)
|
|
end
|
|
|
|
function M.run_all()
|
|
vim.notify("shout: running all tests...", vim.log.levels.INFO)
|
|
run_shout("", function(code, lines)
|
|
show_results(code, lines, nil)
|
|
end)
|
|
end
|
|
|
|
return M
|