fix: only one panel at a time

This commit is contained in:
Barrett Ruth 2025-09-26 09:03:16 -04:00
parent 316b6628db
commit 433a468ee6
3 changed files with 28 additions and 39 deletions

View file

@ -7,8 +7,6 @@
---@field set_problem_id fun(problem_id: string) ---@field set_problem_id fun(problem_id: string)
---@field get_test_cases fun(): table[]? ---@field get_test_cases fun(): table[]?
---@field set_test_cases fun(test_cases: table[]) ---@field set_test_cases fun(test_cases: table[])
---@field is_run_panel_active fun(): boolean
---@field set_run_panel_active fun(active: boolean)
---@field get_saved_session fun(): table? ---@field get_saved_session fun(): table?
---@field set_saved_session fun(session: table) ---@field set_saved_session fun(session: table)
---@field get_context fun(): {platform: string?, contest_id: string?, problem_id: string?} ---@field get_context fun(): {platform: string?, contest_id: string?, problem_id: string?}
@ -28,8 +26,8 @@ local state = {
contest_id = nil, contest_id = nil,
problem_id = nil, problem_id = nil,
test_cases = nil, test_cases = nil,
run_panel_active = false,
saved_session = nil, saved_session = nil,
active_panel = nil,
} }
function M.get_platform() function M.get_platform()
@ -64,14 +62,6 @@ function M.set_test_cases(test_cases)
state.test_cases = test_cases state.test_cases = test_cases
end end
function M.is_run_panel_active()
return state.run_panel_active
end
function M.set_run_panel_active(active)
state.run_panel_active = active
end
function M.get_saved_session() function M.get_saved_session()
return state.saved_session return state.saved_session
end end
@ -149,6 +139,14 @@ function M.has_context()
return state.platform and state.contest_id return state.platform and state.contest_id
end end
function M.get_active_panel()
return state.active_panel
end
function M.set_active_panel(panel)
state.active_panel = panel
end
function M.reset() function M.reset()
state.platform = nil state.platform = nil
state.contest_id = nil state.contest_id = nil

View file

@ -10,7 +10,7 @@ local current_diff_layout = nil
local current_mode = nil local current_mode = nil
function M.toggle_interactive() function M.toggle_interactive()
if state.is_interactive_active then if state.get_active_panel() == 'interactive' then
if state.interactive_buf and vim.api.nvim_buf_is_valid(state.interactive_buf) then if state.interactive_buf and vim.api.nvim_buf_is_valid(state.interactive_buf) then
local job = vim.b[state.interactive_buf].terminal_job_id local job = vim.b[state.interactive_buf].terminal_job_id
if job then if job then
@ -22,11 +22,16 @@ function M.toggle_interactive()
vim.fn.delete(state.saved_interactive_session) vim.fn.delete(state.saved_interactive_session)
state.saved_interactive_session = nil state.saved_interactive_session = nil
end end
state.is_interactive_active = false state.set_active_panel(nil)
logger.log('interactive closed') logger.log('interactive closed')
return return
end end
if state.get_active_panel() then
logger.log('another panel is already active', vim.log.levels.ERROR)
return
end
state.saved_interactive_session = vim.fn.tempname() state.saved_interactive_session = vim.fn.tempname()
vim.cmd(('mksession! %s'):format(state.saved_interactive_session)) vim.cmd(('mksession! %s'):format(state.saved_interactive_session))
vim.cmd('silent only') vim.cmd('silent only')
@ -52,18 +57,18 @@ function M.toggle_interactive()
vim.fn.chansend(vim.b.terminal_job_id, binary .. '\n') vim.fn.chansend(vim.b.terminal_job_id, binary .. '\n')
vim.keymap.set('t', '<c-q>', function() vim.keymap.set('t', config.run_panel.close_key, function()
M.toggle_interactive() M.toggle_interactive()
end, { buffer = term_buf, silent = true }) end, { buffer = term_buf, silent = true })
state.is_interactive_active = true
state.interactive_buf = term_buf state.interactive_buf = term_buf
state.interactive_win = term_win state.interactive_win = term_win
state.set_active_panel('interactive')
logger.log(('interactive opened, running %s'):format(binary)) logger.log(('interactive opened, running %s'):format(binary))
end end
function M.toggle_run_panel(is_debug) function M.toggle_run_panel(is_debug)
if state.is_run_panel_active() then if state.get_active_panel() == 'run' then
if current_diff_layout then if current_diff_layout then
current_diff_layout.cleanup() current_diff_layout.cleanup()
current_diff_layout = nil current_diff_layout = nil
@ -74,12 +79,16 @@ function M.toggle_run_panel(is_debug)
vim.fn.delete(state.saved_session) vim.fn.delete(state.saved_session)
state.saved_session = nil state.saved_session = nil
end end
state.set_active_panel(nil)
state.set_run_panel_active(false)
logger.log('test panel closed') logger.log('test panel closed')
return return
end end
if state.get_active_panel() then
logger.log('another panel is already active', vim.log.levels.ERROR)
return
end
if not state.get_platform() then if not state.get_platform() then
logger.log( logger.log(
'No contest configured. Use :CP <platform> <contest> <problem> to set up first.', 'No contest configured. Use :CP <platform> <contest> <problem> to set up first.',
@ -108,13 +117,11 @@ function M.toggle_run_panel(is_debug)
if config.hooks and config.hooks.before_run then if config.hooks and config.hooks.before_run then
config.hooks.before_run(state) config.hooks.before_run(state)
end end
if is_debug and config.hooks and config.hooks.before_debug then if is_debug and config.hooks and config.hooks.before_debug then
config.hooks.before_debug(state) config.hooks.before_debug(state)
end end
local run = require('cp.runner.run') local run = require('cp.runner.run')
local input_file = state.get_input_file() local input_file = state.get_input_file()
logger.log(('run panel: checking test cases for %s'):format(input_file or 'none')) logger.log(('run panel: checking test cases for %s'):format(input_file or 'none'))
@ -125,7 +132,6 @@ function M.toggle_run_panel(is_debug)
state.saved_session = vim.fn.tempname() state.saved_session = vim.fn.tempname()
vim.cmd(('mksession! %s'):format(state.saved_session)) vim.cmd(('mksession! %s'):format(state.saved_session))
vim.cmd('silent only') vim.cmd('silent only')
local tab_buf = buffer_utils.create_buffer_with_options() local tab_buf = buffer_utils.create_buffer_with_options()
@ -133,13 +139,8 @@ function M.toggle_run_panel(is_debug)
vim.api.nvim_win_set_buf(main_win, tab_buf) vim.api.nvim_win_set_buf(main_win, tab_buf)
vim.api.nvim_set_option_value('filetype', 'cptest', { buf = tab_buf }) vim.api.nvim_set_option_value('filetype', 'cptest', { buf = tab_buf })
local test_windows = { local test_windows = { tab_win = main_win }
tab_win = main_win, local test_buffers = { tab_buf = tab_buf }
}
local test_buffers = {
tab_buf = tab_buf,
}
local test_list_namespace = vim.api.nvim_create_namespace('cp_test_list') local test_list_namespace = vim.api.nvim_create_namespace('cp_test_list')
local setup_keybindings_for_buffer local setup_keybindings_for_buffer
@ -159,10 +160,8 @@ function M.toggle_run_panel(is_debug)
if not test_buffers.tab_buf or not vim.api.nvim_buf_is_valid(test_buffers.tab_buf) then if not test_buffers.tab_buf or not vim.api.nvim_buf_is_valid(test_buffers.tab_buf) then
return return
end end
local run_render = require('cp.runner.run_render') local run_render = require('cp.runner.run_render')
run_render.setup_highlights() run_render.setup_highlights()
local test_state = run.get_run_panel_state() local test_state = run.get_run_panel_state()
local tab_lines, tab_highlights = run_render.render_test_list(test_state) local tab_lines, tab_highlights = run_render.render_test_list(test_state)
buffer_utils.update_buffer_content( buffer_utils.update_buffer_content(
@ -171,7 +170,6 @@ function M.toggle_run_panel(is_debug)
tab_highlights, tab_highlights,
test_list_namespace test_list_namespace
) )
update_diff_panes() update_diff_panes()
end end
@ -180,9 +178,7 @@ function M.toggle_run_panel(is_debug)
if #test_state.test_cases == 0 then if #test_state.test_cases == 0 then
return return
end end
test_state.current_index = (test_state.current_index + delta) % #test_state.test_cases test_state.current_index = (test_state.current_index + delta) % #test_state.test_cases
refresh_run_panel() refresh_run_panel()
end end
@ -242,10 +238,9 @@ function M.toggle_run_panel(is_debug)
end) end)
vim.api.nvim_set_current_win(test_windows.tab_win) vim.api.nvim_set_current_win(test_windows.tab_win)
state.set_run_panel_active(true)
state.test_buffers = test_buffers state.test_buffers = test_buffers
state.test_windows = test_windows state.test_windows = test_windows
state.set_active_panel('run')
local test_state = run.get_run_panel_state() local test_state = run.get_run_panel_state()
logger.log( logger.log(
string.format('test panel opened (%d test cases)', #test_state.test_cases), string.format('test panel opened (%d test cases)', #test_state.test_cases),

View file

@ -33,13 +33,9 @@ describe('cp command parsing', function()
get_problem_id = function() get_problem_id = function()
return 'a' return 'a'
end, end,
is_run_panel_active = function()
return false
end,
set_platform = function() end, set_platform = function() end,
set_contest_id = function() end, set_contest_id = function() end,
set_problem_id = function() end, set_problem_id = function() end,
set_run_panel_active = function() end,
} }
package.loaded['cp.state'] = mock_state package.loaded['cp.state'] = mock_state