diff --git a/lua/cp/execute.lua b/lua/cp/execute.lua index 3c7a2bf..b59a954 100644 --- a/lua/cp/execute.lua +++ b/lua/cp/execute.lua @@ -284,7 +284,13 @@ function M.run_problem(ctx, contest_config, is_debug) local output_buf = vim.fn.bufnr(ctx.output_file) if output_buf ~= -1 then + local was_modifiable = vim.api.nvim_get_option_value('modifiable', { buf = output_buf }) + local was_readonly = vim.api.nvim_get_option_value('readonly', { buf = output_buf }) + vim.api.nvim_set_option_value('readonly', false, { buf = output_buf }) + vim.api.nvim_set_option_value('modifiable', true, { buf = output_buf }) vim.api.nvim_buf_set_lines(output_buf, 0, -1, false, vim.split(formatted_output, '\n')) + vim.api.nvim_set_option_value('modifiable', was_modifiable, { buf = output_buf }) + vim.api.nvim_set_option_value('readonly', was_readonly, { buf = output_buf }) vim.api.nvim_buf_call(output_buf, function() vim.cmd.write() end) diff --git a/lua/cp/highlight.lua b/lua/cp/highlight.lua index 2a60fe0..1f10fac 100644 --- a/lua/cp/highlight.lua +++ b/lua/cp/highlight.lua @@ -151,10 +151,15 @@ end function M.parse_and_apply_diff(bufnr, diff_output, namespace) local parsed = M.parse_git_diff(diff_output) - -- Set buffer content - vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, parsed.content) + local was_modifiable = vim.api.nvim_get_option_value('modifiable', { buf = bufnr }) + local was_readonly = vim.api.nvim_get_option_value('readonly', { buf = bufnr }) + + vim.api.nvim_set_option_value('readonly', false, { buf = bufnr }) + vim.api.nvim_set_option_value('modifiable', true, { buf = bufnr }) + vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, parsed.content) + vim.api.nvim_set_option_value('modifiable', was_modifiable, { buf = bufnr }) + vim.api.nvim_set_option_value('readonly', was_readonly, { buf = bufnr }) - -- Apply highlights M.apply_highlights(bufnr, parsed.highlights, namespace) return parsed.content diff --git a/lua/cp/init.lua b/lua/cp/init.lua index 50e7c25..2bd6a3e 100644 --- a/lua/cp/init.lua +++ b/lua/cp/init.lua @@ -227,17 +227,33 @@ local function toggle_test_panel(is_debug) local highlight = require('cp.highlight') local diff_namespace = highlight.create_namespace() - local function render_test_tabs() - local test_render = require('cp.test_render') - test_render.setup_highlights() - local test_state = test_module.get_test_panel_state() - return test_render.render_test_list(test_state) - end + local test_list_namespace = vim.api.nvim_create_namespace('cp_test_list') - local function update_buffer_content(bufnr, lines) + local function update_buffer_content(bufnr, lines, highlights) + local was_readonly = vim.api.nvim_get_option_value('readonly', { buf = bufnr }) + + vim.api.nvim_set_option_value('readonly', false, { buf = bufnr }) vim.api.nvim_set_option_value('modifiable', true, { buf = bufnr }) vim.api.nvim_buf_set_lines(bufnr, 0, -1, false, lines) vim.api.nvim_set_option_value('modifiable', false, { buf = bufnr }) + vim.api.nvim_set_option_value('readonly', was_readonly, { buf = bufnr }) + + if highlights then + vim.api.nvim_buf_clear_namespace(bufnr, test_list_namespace, 0, -1) + for _, highlight in ipairs(highlights) do + vim.api.nvim_buf_set_extmark( + bufnr, + test_list_namespace, + highlight.line, + highlight.col_start, + { + end_col = highlight.col_end, + hl_group = highlight.highlight_group, + priority = 100, + } + ) + end + end end local function update_expected_pane() @@ -324,8 +340,11 @@ local function toggle_test_panel(is_debug) return end - local tab_lines = render_test_tabs() - update_buffer_content(test_buffers.tab_buf, tab_lines) + local test_render = require('cp.test_render') + test_render.setup_highlights() + local test_state = test_module.get_test_panel_state() + local tab_lines, tab_highlights = test_render.render_test_list(test_state) + update_buffer_content(test_buffers.tab_buf, tab_lines, tab_highlights) update_expected_pane() update_actual_pane() diff --git a/lua/cp/test_render.lua b/lua/cp/test_render.lua index df3d9b3..1170f09 100644 --- a/lua/cp/test_render.lua +++ b/lua/cp/test_render.lua @@ -27,32 +27,53 @@ function M.get_status_info(test_case) end end ----Render test cases list with improved layout +---Render test cases as a clean table ---@param test_state TestPanelState ----@return string[] +---@return string[], table[] lines and highlight positions function M.render_test_list(test_state) local lines = {} + local highlights = {} + + local header = ' # │ Status │ Time │ Exit │ Input' + local separator = + '────┼────────┼──────┼──────┼─────────────────' + table.insert(lines, header) + table.insert(lines, separator) for i, test_case in ipairs(test_state.test_cases) do local is_current = i == test_state.current_index - local prefix = is_current and '> ' or ' ' + local prefix = is_current and '>' or ' ' local status_info = M.get_status_info(test_case) - local status_text = status_info.text ~= '' and status_info.text or '' - local line = string.format('%s%d. %s', prefix, i, status_text) + local num_col = string.format('%s%-2d', prefix, i) + local status_col = string.format(' %-6s', status_info.text) + local time_col = test_case.time_ms and string.format('%4.0fms', test_case.time_ms) or ' — ' + local exit_col = test_case.code and string.format(' %-3d', test_case.code) or ' — ' + local input_col = test_case.input and test_case.input:gsub('\n', ' ') or '' + local line = string.format( + '%s │%s │ %s │%s │ %s', + num_col, + status_col, + time_col, + exit_col, + input_col + ) table.insert(lines, line) - if is_current and test_case.input and test_case.input ~= '' then - for _, input_line in - ipairs(vim.split(test_case.input, '\n', { plain = true, trimempty = false })) - do - table.insert(lines, ' ' .. input_line) - end + if status_info.text ~= '' then + local status_start = #num_col + 3 + local status_end = status_start + #status_info.text + table.insert(highlights, { + line = #lines - 1, + col_start = status_start, + col_end = status_end, + highlight_group = status_info.highlight_group, + }) end end - return lines + return lines, highlights end ---Create status bar content for diff pane