feat(codechef): implement full CodeChef support (#354)

## Problem

CodeChef had no working login, submit, or contest list. The browser
selectors were wrong, the contest list was missing present/past
contests,
and problem/contest URLs were unset.

## Solution

Fix login and submit selectors for the Drupal-based site. Paginate
`/api/list/contests/past` to collect all 228 Starters, then expand each
parent contest into individual division entries (e.g. `START228 (Div.
4)`).
Add language IDs, correct `url`/`contest_url`/`standings_url` in
metadata,
and make `:CP <platform>` open the contest picker directly.
This commit is contained in:
Barrett Ruth 2026-03-06 23:10:44 -05:00 committed by GitHub
parent c7f2af16d4
commit 3c11d609f5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
26 changed files with 336 additions and 158 deletions

View file

@ -331,6 +331,7 @@ setup_keybindings = function(buf)
})
end
---@param test_index? integer
function M.toggle_edit(test_index)
if edit_state then
save_all_tests()

View file

@ -1,3 +1,9 @@
---@class DiffLayout
---@field buffers integer[]
---@field windows integer[]
---@field mode string
---@field cleanup fun()
local M = {}
local helpers = require('cp.helpers')
@ -171,6 +177,11 @@ local function create_single_layout(parent_win, content)
}
end
---@param mode string
---@param parent_win integer
---@param expected_content string
---@param actual_content string
---@return DiffLayout
function M.create_diff_layout(mode, parent_win, expected_content, actual_content)
if mode == 'single' then
return create_single_layout(parent_win, actual_content)
@ -185,6 +196,13 @@ function M.create_diff_layout(mode, parent_win, expected_content, actual_content
end
end
---@param current_diff_layout DiffLayout?
---@param current_mode string?
---@param main_win integer
---@param run table
---@param config cp.Config
---@param setup_keybindings_for_buffer fun(buf: integer)
---@return DiffLayout?, string?
function M.update_diff_panes(
current_diff_layout,
current_mode,

View file

@ -16,6 +16,7 @@ local current_diff_layout = nil
local current_mode = nil
local _run_gen = 0
---@return nil
function M.disable()
local active_panel = state.get_active_panel()
if not active_panel then
@ -351,6 +352,7 @@ local function create_window_layout(output_buf, input_buf)
vim.api.nvim_set_current_win(solution_win)
end
---@return nil
function M.ensure_io_view()
local platform, contest_id, problem_id =
state.get_platform(), state.get_contest_id(), state.get_problem_id()
@ -598,6 +600,9 @@ local function render_io_view_results(io_state, test_indices, mode, combined_res
utils.update_buffer_content(io_state.output_buf, output_lines, final_highlights, output_ns)
end
---@param test_indices_arg integer[]?
---@param debug boolean?
---@param mode? string
function M.run_io_view(test_indices_arg, debug, mode)
_run_gen = _run_gen + 1
local gen = _run_gen
@ -754,10 +759,12 @@ function M.run_io_view(test_indices_arg, debug, mode)
end)
end
---@return nil
function M.cancel_io_view()
_run_gen = _run_gen + 1
end
---@return nil
function M.cancel_interactive()
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