feat(panel): restore cursor
This commit is contained in:
parent
a00799abf4
commit
4e880a2d84
3 changed files with 96 additions and 17 deletions
|
|
@ -92,10 +92,7 @@ function M.compile_generic(language_config, substitutions)
|
|||
if result.code == 0 then
|
||||
logger.log(('compilation successful (%.1fms)'):format(compile_time))
|
||||
else
|
||||
logger.log(
|
||||
('compilation failed (%.1fms): %s'):format(compile_time, result.stderr),
|
||||
vim.log.levels.WARN
|
||||
)
|
||||
logger.log(('compilation failed (%.1fms)'):format(compile_time))
|
||||
end
|
||||
|
||||
return result
|
||||
|
|
@ -202,7 +199,7 @@ end
|
|||
---@param ctx ProblemContext
|
||||
---@param contest_config ContestConfig
|
||||
---@param is_debug? boolean
|
||||
---@return boolean success
|
||||
---@return {success: boolean, stderr: string?}
|
||||
function M.compile_problem(ctx, contest_config, is_debug)
|
||||
vim.validate({
|
||||
ctx = { ctx, 'table' },
|
||||
|
|
@ -214,7 +211,7 @@ function M.compile_problem(ctx, contest_config, is_debug)
|
|||
|
||||
if not language_config then
|
||||
logger.log('No configuration for language: ' .. language, vim.log.levels.ERROR)
|
||||
return false
|
||||
return { success = false, stderr = 'No configuration for language: ' .. language }
|
||||
end
|
||||
|
||||
local substitutions = {
|
||||
|
|
@ -229,16 +226,12 @@ function M.compile_problem(ctx, contest_config, is_debug)
|
|||
language_config.compile = compile_cmd
|
||||
local compile_result = M.compile_generic(language_config, substitutions)
|
||||
if compile_result.code ~= 0 then
|
||||
logger.log(
|
||||
'compilation failed: ' .. (compile_result.stderr or 'unknown error'),
|
||||
vim.log.levels.ERROR
|
||||
)
|
||||
return false
|
||||
return { success = false, stderr = compile_result.stderr or 'unknown error' }
|
||||
end
|
||||
logger.log(('compilation successful (%s)'):format(is_debug and 'debug mode' or 'test mode'))
|
||||
end
|
||||
|
||||
return true
|
||||
return { success = true, stderr = nil }
|
||||
end
|
||||
|
||||
function M.run_problem(ctx, contest_config, is_debug)
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ local state = {
|
|||
test_cases = nil,
|
||||
test_states = {},
|
||||
run_panel_active = false,
|
||||
saved_cursor_pos = nil,
|
||||
saved_source_win = nil,
|
||||
}
|
||||
|
||||
local current_diff_layout = nil
|
||||
|
|
@ -179,6 +181,16 @@ local function toggle_run_panel(is_debug)
|
|||
vim.fn.delete(state.saved_session)
|
||||
state.saved_session = nil
|
||||
end
|
||||
|
||||
if state.saved_source_win and vim.api.nvim_win_is_valid(state.saved_source_win) then
|
||||
vim.api.nvim_set_current_win(state.saved_source_win)
|
||||
if state.saved_cursor_pos then
|
||||
pcall(vim.api.nvim_win_set_cursor, 0, state.saved_cursor_pos)
|
||||
end
|
||||
end
|
||||
|
||||
state.saved_cursor_pos = nil
|
||||
state.saved_source_win = nil
|
||||
state.run_panel_active = false
|
||||
logger.log('test panel closed')
|
||||
return
|
||||
|
|
@ -192,6 +204,9 @@ local function toggle_run_panel(is_debug)
|
|||
return
|
||||
end
|
||||
|
||||
state.saved_cursor_pos = vim.api.nvim_win_get_cursor(0)
|
||||
state.saved_source_win = vim.api.nvim_get_current_win()
|
||||
|
||||
local problem_id = get_current_problem()
|
||||
if not problem_id then
|
||||
return
|
||||
|
|
@ -326,8 +341,31 @@ local function toggle_run_panel(is_debug)
|
|||
}
|
||||
end
|
||||
|
||||
local function create_single_layout(parent_win, content)
|
||||
local buf = create_buffer_with_options()
|
||||
local lines = vim.split(content, '\n', { plain = true, trimempty = true })
|
||||
update_buffer_content(buf, lines, {})
|
||||
|
||||
vim.api.nvim_set_current_win(parent_win)
|
||||
vim.cmd.split()
|
||||
local win = vim.api.nvim_get_current_win()
|
||||
vim.api.nvim_win_set_buf(win, buf)
|
||||
vim.api.nvim_set_option_value('filetype', 'cptest', { buf = buf })
|
||||
|
||||
return {
|
||||
buffers = { buf },
|
||||
windows = { win },
|
||||
cleanup = function()
|
||||
pcall(vim.api.nvim_win_close, win, true)
|
||||
pcall(vim.api.nvim_buf_delete, buf, { force = true })
|
||||
end,
|
||||
}
|
||||
end
|
||||
|
||||
local function create_diff_layout(mode, parent_win, expected_content, actual_content)
|
||||
if mode == 'git' then
|
||||
if mode == 'single' then
|
||||
return create_single_layout(parent_win, actual_content)
|
||||
elseif mode == 'git' then
|
||||
return create_git_diff_layout(parent_win, expected_content, actual_content)
|
||||
else
|
||||
return create_vim_diff_layout(parent_win, expected_content, actual_content)
|
||||
|
|
@ -344,14 +382,18 @@ local function toggle_run_panel(is_debug)
|
|||
|
||||
local expected_content = current_test.expected or ''
|
||||
local actual_content = current_test.actual or '(not run yet)'
|
||||
local should_show_diff = current_test.status == 'fail' and current_test.actual
|
||||
local is_compilation_failure = current_test.error
|
||||
and current_test.error:match('Compilation failed')
|
||||
local should_show_diff = current_test.status == 'fail'
|
||||
and current_test.actual
|
||||
and not is_compilation_failure
|
||||
|
||||
if not should_show_diff then
|
||||
expected_content = expected_content
|
||||
actual_content = actual_content
|
||||
end
|
||||
|
||||
local desired_mode = config.run_panel.diff_mode
|
||||
local desired_mode = is_compilation_failure and 'single' or config.run_panel.diff_mode
|
||||
|
||||
if current_diff_layout and current_mode ~= desired_mode then
|
||||
local saved_pos = vim.api.nvim_win_get_cursor(0)
|
||||
|
|
@ -380,7 +422,10 @@ local function toggle_run_panel(is_debug)
|
|||
setup_keybindings_for_buffer(buf)
|
||||
end
|
||||
else
|
||||
if desired_mode == 'git' then
|
||||
if desired_mode == 'single' then
|
||||
local lines = vim.split(actual_content, '\n', { plain = true, trimempty = true })
|
||||
update_buffer_content(current_diff_layout.buffers[1], lines, {})
|
||||
elseif desired_mode == 'git' then
|
||||
local diff_backend = require('cp.diff')
|
||||
local backend = diff_backend.get_best_backend('git')
|
||||
local diff_result = backend.render(expected_content, actual_content)
|
||||
|
|
@ -410,6 +455,8 @@ local function toggle_run_panel(is_debug)
|
|||
vim.api.nvim_win_call(current_diff_layout.windows[2], function()
|
||||
vim.cmd.diffthis()
|
||||
end)
|
||||
vim.api.nvim_set_option_value('foldcolumn', '0', { win = current_diff_layout.windows[1] })
|
||||
vim.api.nvim_set_option_value('foldcolumn', '0', { win = current_diff_layout.windows[2] })
|
||||
else
|
||||
vim.api.nvim_set_option_value('diff', false, { win = current_diff_layout.windows[1] })
|
||||
vim.api.nvim_set_option_value('diff', false, { win = current_diff_layout.windows[2] })
|
||||
|
|
@ -456,6 +503,12 @@ local function toggle_run_panel(is_debug)
|
|||
config.run_panel.diff_mode = config.run_panel.diff_mode == 'vim' and 'git' or 'vim'
|
||||
refresh_run_panel()
|
||||
end, { buffer = buf, silent = true })
|
||||
vim.keymap.set('n', config.run_panel.next_test_key, function()
|
||||
navigate_test_case(1)
|
||||
end, { buffer = buf, silent = true })
|
||||
vim.keymap.set('n', config.run_panel.prev_test_key, function()
|
||||
navigate_test_case(-1)
|
||||
end, { buffer = buf, silent = true })
|
||||
end
|
||||
|
||||
vim.keymap.set('n', config.run_panel.next_test_key, function()
|
||||
|
|
@ -477,8 +530,11 @@ local function toggle_run_panel(is_debug)
|
|||
|
||||
local execute_module = require('cp.execute')
|
||||
local contest_config = config.contests[state.platform]
|
||||
if execute_module.compile_problem(ctx, contest_config, is_debug) then
|
||||
local compile_result = execute_module.compile_problem(ctx, contest_config, is_debug)
|
||||
if compile_result.success then
|
||||
test_module.run_all_test_cases(ctx, contest_config, config)
|
||||
else
|
||||
test_module.handle_compilation_failure(compile_result.stderr)
|
||||
end
|
||||
|
||||
refresh_run_panel()
|
||||
|
|
|
|||
|
|
@ -192,7 +192,12 @@ local function run_single_test_case(ctx, contest_config, cp_config, test_case)
|
|||
status = 'fail',
|
||||
actual = '',
|
||||
error = 'Compilation failed: ' .. (compile_result.stderr or 'Unknown error'),
|
||||
stderr = compile_result.stderr or '',
|
||||
time_ms = 0,
|
||||
code = compile_result.code,
|
||||
ok = false,
|
||||
signal = nil,
|
||||
timed_out = false,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
@ -217,6 +222,15 @@ local function run_single_test_case(ctx, contest_config, cp_config, test_case)
|
|||
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$', '')
|
||||
|
||||
if stderr_output ~= '' then
|
||||
if actual_output ~= '' then
|
||||
actual_output = actual_output .. '\n\n--- stderr ---\n' .. stderr_output
|
||||
else
|
||||
actual_output = '--- stderr ---\n' .. stderr_output
|
||||
end
|
||||
end
|
||||
|
||||
local max_lines = cp_config.run_panel.max_output_lines
|
||||
local output_lines = vim.split(actual_output, '\n')
|
||||
|
|
@ -251,6 +265,7 @@ local function run_single_test_case(ctx, contest_config, cp_config, test_case)
|
|||
status = status,
|
||||
actual = actual_output,
|
||||
error = result.code ~= 0 and result.stderr or nil,
|
||||
stderr = result.stderr or '',
|
||||
time_ms = execution_time,
|
||||
code = result.code,
|
||||
ok = ok,
|
||||
|
|
@ -303,6 +318,7 @@ function M.run_test_case(ctx, contest_config, cp_config, index)
|
|||
test_case.status = result.status
|
||||
test_case.actual = result.actual
|
||||
test_case.error = result.error
|
||||
test_case.stderr = result.stderr
|
||||
test_case.time_ms = result.time_ms
|
||||
test_case.code = result.code
|
||||
test_case.ok = result.ok
|
||||
|
|
@ -329,4 +345,18 @@ function M.get_run_panel_state()
|
|||
return run_panel_state
|
||||
end
|
||||
|
||||
function M.handle_compilation_failure(compilation_stderr)
|
||||
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.error = 'Compilation failed'
|
||||
test_case.stderr = ''
|
||||
test_case.time_ms = 0
|
||||
test_case.code = 1
|
||||
test_case.ok = false
|
||||
test_case.signal = nil
|
||||
test_case.timed_out = false
|
||||
end
|
||||
end
|
||||
|
||||
return M
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue