feat: panel formatting

This commit is contained in:
Barrett Ruth 2025-09-16 00:12:56 -04:00
parent dfcb377b98
commit 087c4ffa43
7 changed files with 89 additions and 83 deletions

View file

@ -21,4 +21,23 @@ M.canonical_filetypes = {
[M.PYTHON] = "python",
}
---@type table<number, string>
M.signal_codes = {
[128] = "SIGILL",
[130] = "SIGINT",
[131] = "SIGQUIT",
[132] = "SIGILL",
[133] = "SIGTRAP",
[134] = "SIGABRT",
[135] = "SIGBUS",
[136] = "SIGFPE",
[137] = "SIGKILL",
[138] = "SIGUSR1",
[139] = "SIGSEGV",
[140] = "SIGUSR2",
[141] = "SIGPIPE",
[142] = "SIGALRM",
[143] = "SIGTERM",
}
return M

View file

@ -64,23 +64,6 @@ local function build_command(cmd_template, executable, substitutions)
return cmd
end
local signal_codes = {
[128] = "SIGILL",
[130] = "SIGINT",
[131] = "SIGQUIT",
[132] = "SIGILL",
[133] = "SIGTRAP",
[134] = "SIGABRT",
[135] = "SIGBUS",
[136] = "SIGFPE",
[137] = "SIGKILL",
[138] = "SIGUSR1",
[139] = "SIGSEGV",
[140] = "SIGUSR2",
[141] = "SIGPIPE",
[142] = "SIGALRM",
[143] = "SIGTERM",
}
local function ensure_directories()
vim.system({ "mkdir", "-p", "build", "io" }):wait()
@ -176,7 +159,7 @@ local function format_output(exec_result, expected_file, is_debug)
if exec_result.timed_out then
table.insert(metadata_lines, "[code]: 124 (TIMEOUT)")
elseif exec_result.code >= 128 then
local signal_name = signal_codes[exec_result.code] or "SIGNAL"
local signal_name = constants.signal_codes[exec_result.code] or "SIGNAL"
table.insert(metadata_lines, ("[code]: %d (%s)"):format(exec_result.code, signal_name))
else
table.insert(metadata_lines, ("[code]: %d"):format(exec_result.code))
@ -193,17 +176,17 @@ local function format_output(exec_result, expected_file, is_debug)
table.remove(actual_lines)
end
local matches = #actual_lines == #expected_content
if matches then
local ok = #actual_lines == #expected_content
if ok then
for i, line in ipairs(actual_lines) do
if line ~= expected_content[i] then
matches = false
ok = false
break
end
end
end
table.insert(metadata_lines, ("[matches]: %s"):format(matches and "true" or "false"))
table.insert(metadata_lines, ("[ok]: %s"):format(ok and "true" or "false"))
end
return table.concat(output_lines, "") .. "\n" .. table.concat(metadata_lines, "\n")

View file

@ -281,10 +281,45 @@ local function toggle_test_panel()
local test_state = test_module.get_test_panel_state()
local tab_lines = {}
local max_status_width = 0
local max_code_width = 0
local max_time_width = 0
for _, test_case in ipairs(test_state.test_cases) do
local status_text = test_case.status == "pending" and "" or string.upper(test_case.status)
max_status_width = math.max(max_status_width, #status_text)
if test_case.code then
max_code_width = math.max(max_code_width, #tostring(test_case.code))
end
if test_case.time_ms then
local time_text = string.format("%.0fms", test_case.time_ms)
max_time_width = math.max(max_time_width, #time_text)
end
end
for i, test_case in ipairs(test_state.test_cases) do
local status_text = test_case.status == "pending" and "?" or string.upper(test_case.status)
local prefix = i == test_state.current_index and "> " or " "
local tab = string.format("%s%d. %s", prefix, i, status_text)
local tab = string.format("%s%d.", prefix, i)
if test_case.code then
tab = tab .. string.format(" [code:%-" .. max_code_width .. "s]", tostring(test_case.code))
end
if test_case.time_ms then
local time_text = string.format("%.0fms", test_case.time_ms)
tab = tab .. string.format(" [time:%-" .. max_time_width .. "s]", time_text)
end
if test_case.ok ~= nil then
tab = tab .. string.format(" [ok:%-5s]", tostring(test_case.ok))
end
if test_case.signal then
tab = tab .. string.format(" [%s]", test_case.signal)
end
table.insert(tab_lines, tab)
end
@ -301,6 +336,7 @@ local function toggle_test_panel()
return tab_lines
end
local function update_expected_pane()
local test_state = test_module.get_test_panel_state()
local current_test = test_state.test_cases[test_state.current_index]

View file

@ -259,10 +259,6 @@ function M.scrape_problem(ctx)
local input_content = test_case.input:gsub("\r", "")
local expected_content = test_case.output:gsub("\r", "")
if ctx.contest == "atcoder" then
input_content = "1\n" .. input_content
end
vim.fn.writefile(vim.split(input_content, "\n", true), input_file)
vim.fn.writefile(vim.split(expected_content, "\n", true), expected_file)
end

View file

@ -7,6 +7,10 @@
---@field time_ms number?
---@field error string?
---@field selected boolean
---@field code number?
---@field ok boolean?
---@field signal string?
---@field timed_out boolean?
---@class TestPanelState
---@field test_cases TestCase[]
@ -18,6 +22,7 @@
local M = {}
local logger = require("cp.log")
local constants = require("cp.constants")
---@type TestPanelState
local test_panel_state = {
@ -89,10 +94,6 @@ local function parse_test_cases_from_files(input_file, expected_file)
local input_content = table.concat(vim.fn.readfile(individual_input_file), "\n")
local expected_content = table.concat(vim.fn.readfile(individual_expected_file), "\n")
if input_content:match("^1\n") then
input_content = input_content:gsub("^1\n", "")
end
table.insert(test_cases, create_test_case(i, input_content, expected_content))
i = i + 1
else
@ -180,22 +181,32 @@ local function run_single_test_case(ctx, contest_config, test_case)
local actual_output = (result.stdout or ""):gsub("\n$", "")
local expected_output = test_case.expected:gsub("\n$", "")
local matches = actual_output == expected_output
local ok = actual_output == expected_output
local status
if result.code == 143 or result.code == 124 then
local timed_out = result.code == 143 or result.code == 124
if timed_out then
status = "timeout"
elseif result.code == 0 and matches then
elseif result.code == 0 and ok then
status = "pass"
else
status = "fail"
end
local signal = nil
if result.code >= 128 then
signal = constants.signal_codes[result.code]
end
return {
status = status,
actual = actual_output,
error = result.code ~= 0 and result.stderr or nil,
time_ms = execution_time,
code = result.code,
ok = ok,
signal = signal,
timed_out = timed_out,
}
end
@ -235,6 +246,10 @@ function M.run_test_case(ctx, contest_config, index)
test_case.actual = result.actual
test_case.error = result.error
test_case.time_ms = result.time_ms
test_case.code = result.code
test_case.ok = result.ok
test_case.signal = result.signal
test_case.timed_out = result.timed_out
return true
end