feat(panel): color stder

This commit is contained in:
Barrett Ruth 2025-09-20 10:41:52 -04:00
parent 4e880a2d84
commit 21b7765105
5 changed files with 387 additions and 12 deletions

View file

@ -4,6 +4,7 @@
---@field expected string
---@field status "pending"|"pass"|"fail"|"running"|"timeout"
---@field actual string?
---@field actual_highlights table[]?
---@field time_ms number?
---@field error string?
---@field selected boolean
@ -216,19 +217,41 @@ local function run_single_test_case(ctx, contest_config, cp_config, test_case)
.system(run_cmd, {
stdin = stdin_content,
timeout = timeout_ms,
text = true,
text = false,
})
:wait()
local execution_time = (vim.uv.hrtime() - start_time) / 1000000
local actual_output = (result.stdout or ''):gsub('\n$', '')
local stderr_output = (result.stderr or ''):gsub('\n$', '')
local ansi = require('cp.ansi')
local stdout_str = ansi.bytes_to_string(result.stdout or '')
local stderr_str = ansi.bytes_to_string(result.stderr or '')
local actual_output = stdout_str:gsub('\n$', '')
local stderr_output = stderr_str:gsub('\n$', '')
local actual_highlights = {}
if stderr_output ~= '' then
local stderr_parsed = ansi.parse_ansi_text(stderr_output)
local clean_stderr = table.concat(stderr_parsed.lines, '\n')
local line_offset
if actual_output ~= '' then
actual_output = actual_output .. '\n\n--- stderr ---\n' .. stderr_output
local stdout_lines = vim.split(actual_output, '\n')
line_offset = #stdout_lines + 2 -- +1 for empty line, +1 for "--- stderr ---"
actual_output = actual_output .. '\n\n--- stderr ---\n' .. clean_stderr
else
actual_output = '--- stderr ---\n' .. stderr_output
line_offset = 1 -- +1 for "--- stderr ---"
actual_output = '--- stderr ---\n' .. clean_stderr
end
for _, highlight in ipairs(stderr_parsed.highlights) do
table.insert(actual_highlights, {
line = highlight.line + line_offset,
col_start = highlight.col_start,
col_end = highlight.col_end,
highlight_group = highlight.highlight_group,
})
end
end
@ -264,6 +287,7 @@ local function run_single_test_case(ctx, contest_config, cp_config, test_case)
return {
status = status,
actual = actual_output,
actual_highlights = actual_highlights,
error = result.code ~= 0 and result.stderr or nil,
stderr = result.stderr or '',
time_ms = execution_time,
@ -317,6 +341,7 @@ function M.run_test_case(ctx, contest_config, cp_config, index)
test_case.status = result.status
test_case.actual = result.actual
test_case.actual_highlights = result.actual_highlights
test_case.error = result.error
test_case.stderr = result.stderr
test_case.time_ms = result.time_ms
@ -346,9 +371,44 @@ function M.get_run_panel_state()
end
function M.handle_compilation_failure(compilation_stderr)
local ansi = require('cp.ansi')
local logger = require('cp.log')
local clean_text = 'Compilation failed'
local highlights = {}
if compilation_stderr and compilation_stderr ~= '' then
logger.log('Raw compilation stderr length: ' .. #compilation_stderr)
logger.log('Has ANSI codes: ' .. tostring(compilation_stderr:find('\027%[[%d;]*m') ~= nil))
-- Show first 200 chars to see actual ANSI sequences
local sample = compilation_stderr:sub(1, 200):gsub('\027', '\\027')
logger.log('Stderr sample: ' .. sample)
local parsed = ansi.parse_ansi_text(compilation_stderr)
clean_text = table.concat(parsed.lines, '\n')
highlights = parsed.highlights
logger.log('Parsed highlights count: ' .. #highlights)
for i, hl in ipairs(highlights) do
logger.log(
'Highlight '
.. i
.. ': line='
.. hl.line
.. ' col='
.. hl.col_start
.. '-'
.. hl.col_end
.. ' group='
.. (hl.highlight_group or 'nil')
)
end
end
for i, test_case in ipairs(run_panel_state.test_cases) do
test_case.status = 'fail'
test_case.actual = compilation_stderr or 'Compilation failed'
test_case.actual = clean_text
test_case.actual_highlights = highlights
test_case.error = 'Compilation failed'
test_case.stderr = ''
test_case.time_ms = 0