local M = {} local buffer_utils = require('cp.utils.buffer') local config_module = require('cp.config') local layouts = require('cp.ui.layouts') local logger = require('cp.log') local problem = require('cp.problem') local state = require('cp.state') local current_diff_layout = nil local current_mode = nil local function get_current_problem() local setup_nav = require('cp.setup.navigation') return setup_nav.get_current_problem() end function M.toggle_run_panel(is_debug) if state.run_panel_active then if current_diff_layout then current_diff_layout.cleanup() current_diff_layout = nil current_mode = nil end if state.saved_session then vim.cmd(('source %s'):format(state.saved_session)) vim.fn.delete(state.saved_session) state.saved_session = nil end state.set_run_panel_active(false) logger.log('test panel closed') return end if not state.get_platform() then logger.log( 'No contest configured. Use :CP to set up first.', vim.log.levels.ERROR ) return end local problem_id = get_current_problem() if not problem_id then return end local config = config_module.get_config() local ctx = problem.create_context( state.get_platform() or '', state.get_contest_id() or '', state.get_problem_id(), config ) local run = require('cp.runner.run') if not run.load_test_cases(ctx, state) then logger.log('no test cases found', vim.log.levels.WARN) return end state.saved_session = vim.fn.tempname() vim.cmd(('mksession! %s'):format(state.saved_session)) vim.cmd('silent only') local tab_buf = buffer_utils.create_buffer_with_options() local main_win = vim.api.nvim_get_current_win() vim.api.nvim_win_set_buf(main_win, tab_buf) vim.api.nvim_set_option_value('filetype', 'cptest', { buf = tab_buf }) local test_windows = { tab_win = main_win, } local test_buffers = { tab_buf = tab_buf, } local highlight = require('cp.ui.highlight') local diff_namespace = highlight.create_namespace() local test_list_namespace = vim.api.nvim_create_namespace('cp_test_list') local ansi_namespace = vim.api.nvim_create_namespace('cp_ansi_highlights') local function update_diff_panes() current_diff_layout, current_mode = layouts.update_diff_panes( current_diff_layout, current_mode, main_win, run, config, setup_keybindings_for_buffer ) end local function refresh_run_panel() if not test_buffers.tab_buf or not vim.api.nvim_buf_is_valid(test_buffers.tab_buf) then return end local run_render = require('cp.runner.run_render') run_render.setup_highlights() local test_state = run.get_run_panel_state() local tab_lines, tab_highlights = run_render.render_test_list(test_state) buffer_utils.update_buffer_content( test_buffers.tab_buf, tab_lines, tab_highlights, test_list_namespace ) update_diff_panes() end local function navigate_test_case(delta) local test_state = run.get_run_panel_state() if #test_state.test_cases == 0 then return end test_state.current_index = test_state.current_index + delta if test_state.current_index < 1 then test_state.current_index = #test_state.test_cases elseif test_state.current_index > #test_state.test_cases then test_state.current_index = 1 end refresh_run_panel() end setup_keybindings_for_buffer = function(buf) vim.keymap.set('n', 'q', function() M.toggle_run_panel() end, { buffer = buf, silent = true }) vim.keymap.set('n', config.run_panel.toggle_diff_key, function() local modes = { 'none', 'git', 'vim' } local current_idx = nil for i, mode in ipairs(modes) do if config.run_panel.diff_mode == mode then current_idx = i break end end current_idx = current_idx or 1 config.run_panel.diff_mode = modes[(current_idx % #modes) + 1] 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() navigate_test_case(1) end, { buffer = test_buffers.tab_buf, silent = true }) vim.keymap.set('n', config.run_panel.prev_test_key, function() navigate_test_case(-1) end, { buffer = test_buffers.tab_buf, silent = true }) setup_keybindings_for_buffer(test_buffers.tab_buf) if config.hooks and config.hooks.before_run then config.hooks.before_run(ctx) end if is_debug and config.hooks and config.hooks.before_debug then config.hooks.before_debug(ctx) end local execute = require('cp.runner.execute') local contest_config = config.contests[state.get_platform() or ''] local compile_result = execute.compile_problem(ctx, contest_config, is_debug) if compile_result.success then run.run_all_test_cases(ctx, contest_config, config) else run.handle_compilation_failure(compile_result.output) end refresh_run_panel() vim.schedule(function() if config.run_panel.ansi then local ansi = require('cp.ui.ansi') ansi.setup_highlight_groups() end if current_diff_layout then update_diff_panes() end end) vim.api.nvim_set_current_win(test_windows.tab_win) state.run_panel_active = true state.test_buffers = test_buffers state.test_windows = test_windows local test_state = run.get_run_panel_state() logger.log( string.format('test panel opened (%d test cases)', #test_state.test_cases), vim.log.levels.INFO ) end return M