diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..aa57334 --- /dev/null +++ b/.envrc @@ -0,0 +1,3 @@ +VIRTUAL_ENV="$PWD/.venv" +PATH_add "$VIRTUAL_ENV/bin" +export VIRTUAL_ENV diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml new file mode 100644 index 0000000..bf6bcea --- /dev/null +++ b/.github/workflows/ci.yaml @@ -0,0 +1,112 @@ +name: ci +on: + workflow_call: + pull_request: + branches: [main] + push: + branches: [main] + +jobs: + changes: + runs-on: ubuntu-latest + outputs: + lua: ${{ steps.changes.outputs.lua }} + python: ${{ steps.changes.outputs.python }} + steps: + - uses: actions/checkout@v4 + - uses: dorny/paths-filter@v3 + id: changes + with: + filters: | + lua: + - 'lua/**' + - 'spec/**' + - 'plugin/**' + - 'after/**' + - 'ftdetect/**' + - '*.lua' + - '.luarc.json' + - 'stylua.toml' + - 'selene.toml' + python: + - 'scripts/**' + - 'scrapers/**' + - 'tests/**' + - 'pyproject.toml' + - 'uv.lock' + + lua-format: + runs-on: ubuntu-latest + needs: changes + if: ${{ needs.changes.outputs.lua == 'true' }} + steps: + - uses: actions/checkout@v4 + - uses: JohnnyMorganz/stylua-action@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + version: 2.1.0 + args: --check . + + lua-lint: + runs-on: ubuntu-latest + needs: changes + if: ${{ needs.changes.outputs.lua == 'true' }} + steps: + - uses: actions/checkout@v4 + - uses: NTBBloodbath/selene-action@v1.0.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + args: --display-style quiet . + + lua-typecheck: + runs-on: ubuntu-latest + needs: changes + if: ${{ needs.changes.outputs.lua == 'true' }} + steps: + - uses: actions/checkout@v4 + - uses: mrcjkb/lua-typecheck-action@v0 + with: + checklevel: Warning + directories: lua + configpath: .luarc.json + + python-format: + runs-on: ubuntu-latest + needs: changes + if: ${{ needs.changes.outputs.python == 'true' }} + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/setup-uv@v4 + - run: uv tool install ruff + - run: ruff format --check . + + python-lint: + runs-on: ubuntu-latest + needs: changes + if: ${{ needs.changes.outputs.python == 'true' }} + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/setup-uv@v4 + - run: uv tool install ruff + - run: ruff check . + + python-typecheck: + runs-on: ubuntu-latest + needs: changes + if: ${{ needs.changes.outputs.python == 'true' }} + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/setup-uv@v4 + - run: uv sync --dev + - run: uvx ty check . + + python-test: + runs-on: ubuntu-latest + needs: changes + if: ${{ needs.changes.outputs.python == 'true' }} + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/setup-uv@v4 + - run: uv sync --dev + - run: uv run camoufox fetch + - run: uv run pytest tests/ -v diff --git a/.github/workflows/quality.yaml b/.github/workflows/quality.yaml index 664b33e..731e74b 100644 --- a/.github/workflows/quality.yaml +++ b/.github/workflows/quality.yaml @@ -28,7 +28,6 @@ jobs: - '*.lua' - '.luarc.json' - '*.toml' - - 'vim.yaml' python: - 'scripts/**/.py' - 'scrapers/**/*.py' @@ -46,8 +45,11 @@ jobs: if: ${{ needs.changes.outputs.lua == 'true' }} steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v31 - - run: nix develop --command stylua --check . + - uses: JohnnyMorganz/stylua-action@v4 + with: + token: ${{ secrets.GITHUB_TOKEN }} + version: 2.1.0 + args: --check . lua-lint: name: Lua Lint Check @@ -56,8 +58,11 @@ jobs: if: ${{ needs.changes.outputs.lua == 'true' }} steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v31 - - run: nix develop --command selene --display-style quiet . + - name: Lint with Selene + uses: NTBBloodbath/selene-action@v1.0.0 + with: + token: ${{ secrets.GITHUB_TOKEN }} + args: --display-style quiet . lua-typecheck: name: Lua Type Check @@ -122,5 +127,15 @@ jobs: if: ${{ needs.changes.outputs.markdown == 'true' }} steps: - uses: actions/checkout@v4 - - uses: cachix/install-nix-action@v31 - - run: nix develop --command prettier --check . + - name: Setup pnpm + uses: pnpm/action-setup@v4 + with: + version: 8 + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: '20' + - name: Install prettier + run: pnpm add -g prettier@3.1.0 + - name: Check markdown formatting with prettier + run: prettier --check . diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 34bd84f..ed7be0c 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -44,7 +44,9 @@ jobs: - uses: actions/checkout@v4 - name: Install uv uses: astral-sh/setup-uv@v4 - - name: Install dependencies + - name: Install dependencies with pytest run: uv sync --dev + - name: Fetch camoufox data + run: uv run camoufox fetch - name: Run Python tests run: uv run pytest tests/ -v diff --git a/.gitignore b/.gitignore index a489c55..45bc345 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,3 @@ __pycache__ .claude/ node_modules/ - -.envrc -.direnv/ diff --git a/.luarc.json b/.luarc.json index 727793d..3ccfeda 100644 --- a/.luarc.json +++ b/.luarc.json @@ -1,21 +1,8 @@ { - "runtime": { - "version": "LuaJIT", - "path": ["lua/?.lua", "lua/?/init.lua"] - }, - "diagnostics": { - "globals": ["vim"] - }, - "workspace": { - "library": [ - "$VIMRUNTIME/lua", - "${3rd}/luv/library", - "${3rd}/busted/library" - ], - "checkThirdParty": false, - "ignoreDir": [".direnv"] - }, - "completion": { - "callSnippet": "Replace" - } + "runtime.version": "Lua 5.1", + "runtime.path": ["lua/?.lua", "lua/?/init.lua"], + "diagnostics.globals": ["vim"], + "workspace.library": ["$VIMRUNTIME/lua", "${3rd}/luv/library"], + "workspace.checkThirdParty": false, + "completion.callSnippet": "Replace" } diff --git a/.styluaignore b/.styluaignore deleted file mode 100644 index 9b42106..0000000 --- a/.styluaignore +++ /dev/null @@ -1 +0,0 @@ -.direnv/ diff --git a/README.md b/README.md index 427496d..cf82417 100644 --- a/README.md +++ b/README.md @@ -28,12 +28,11 @@ Install using your package manager of choice or via luarocks install cp.nvim ``` -## Dependencies +## Optional Dependencies +- [uv](https://docs.astral.sh/uv/) for problem scraping - GNU [time](https://www.gnu.org/software/time/) and [timeout](https://www.gnu.org/software/coreutils/manual/html_node/timeout-invocation.html) -- [uv](https://docs.astral.sh/uv/) or [nix](https://nixos.org/) for problem - scraping ## Quick Start diff --git a/doc/cp.nvim.txt b/doc/cp.nvim.txt index e6c4c61..d6d1d73 100644 --- a/doc/cp.nvim.txt +++ b/doc/cp.nvim.txt @@ -3,46 +3,13 @@ Author: Barrett Ruth License: Same terms as Vim itself (see |license|) -============================================================================== -CONTENTS *cp-contents* - - 1. Introduction .................................................. |cp.nvim| - 2. Requirements ........................................ |cp-requirements| - 3. Setup ........................................................ |cp-setup| - 4. Configuration ................................................ |cp-config| - 5. Commands .................................................. |cp-commands| - 6. Mappings .................................................. |cp-mappings| - 7. Language Selection .................................. |cp-lang-selection| - 8. Workflow .................................................. |cp-workflow| - 9. Workflow Example ............................................ |cp-example| - 10. Verdict Formatting ................................. |cp-verdict-format| - 11. Picker Integration .......................................... |cp-picker| - 12. Picker Keymaps ........................................ |cp-picker-keys| - 13. Panel ........................................................ |cp-panel| - 14. Interactive Mode .......................................... |cp-interact| - 15. Stress Testing .............................................. |cp-stress| - 16. Race .......................................................... |cp-race| - 17. Credentials ............................................ |cp-credentials| - 18. Submit ...................................................... |cp-submit| - 19. Submit Language Versions ......................... |cp-submit-language| - 20. Open ......................................................... |cp-open| - 21. ANSI Colors ................................................... |cp-ansi| - 22. Highlight Groups ........................................ |cp-highlights| - 23. Terminal Colors .................................... |cp-terminal-colors| - 24. Highlight Customization .......................... |cp-highlight-custom| - 25. Helpers .................................................... |cp-helpers| - 26. Statusline Integration .................................. |cp-statusline| - 27. Panel Keymaps .......................................... |cp-panel-keys| - 28. File Structure ................................................ |cp-files| - 28. Health Check ................................................ |cp-health| - ============================================================================== INTRODUCTION *cp.nvim* cp.nvim is a competitive programming plugin that automates problem setup, compilation, and testing workflow for online judges. -Supported platforms: AtCoder, CodeChef, Codeforces, CSES, Kattis, USACO +Supported platforms (for now!): AtCoder, Codeforces, CSES ============================================================================== REQUIREMENTS *cp-requirements* @@ -52,20 +19,195 @@ REQUIREMENTS *cp-requirements* - uv package manager (https://docs.astral.sh/uv/) ============================================================================== -SETUP *cp-setup* +COMMANDS *cp-commands* -Load cp.nvim with your package manager. For example, with lazy.nvim: >lua - { 'barrettruth/cp.nvim' } +:CP *:CP* + cp.nvim uses a single :CP command with intelligent argument parsing: + + Setup Commands ~ + :CP {platform} {contest_id} [--lang {language}] + Full setup: set platform and load contest metadata. + Scrapes test cases and creates source file. + --lang: Use specific language (default: platform default) + Examples: > + :CP codeforces 1933 + :CP codeforces 1933 --lang python +< + View Commands ~ + :CP run [all|n|n,m,...] [--debug] + Run tests in I/O view (see |cp-io-view|). + Lightweight split showing test verdicts. + + Execution modes: + • :CP run Combined: single execution with all tests + (auto-switches to individual when multiple samples) + • :CP run all Individual: N separate executions + • :CP run n Individual: run test n only + • :CP run n,m,... Individual: run specific tests (e.g. nth and mth) + + --debug: Use debug build (builds to build/.dbg) + + Combined mode runs all test inputs in one execution (matching + platform behavior for multi-test problems). When a problem has + multiple independent sample test cases, :CP run auto-switches to + individual mode to run each sample separately. + + Examples: > + :CP run " Combined: all tests, one execution + :CP run all " Individual: all tests, N executions + :CP run 2 " Individual: test 2 only + :CP run 1,3,5 " Individual: tests 1, 3, and 5 + :CP run all --debug " Individual with debug build +< + :CP panel [--debug] [n] + Open full-screen test panel (see |cp-panel|). + Aggregate table with diff modes for detailed analysis. + Optional [n] focuses on specific test. + --debug: Use debug build (with sanitizers, etc.) + Examples: > + :CP panel " All tests + :CP panel --debug 3 " Test 3, debug build +< + + :CP pick [--lang {language}] + Launch configured picker for interactive + platform/contest selection. + --lang: Pre-select language for chosen contest. + Example: > + :CP pick + :CP pick --lang python +< + + :CP interact [script] + Open an interactive terminal for the current problem. + If an executable interactor is provided, runs the compiled + binary against the source file (see + *cp-interact*). Otherwise, runs the source + file. Only valid for interactive problems. + + Navigation Commands ~ + :CP next [--lang {language}] + Navigate to next problem in current contest. + Stops at last problem (no wrapping). + --lang: Use specific language for next problem. + By default, preserves current file's language if + enabled for the new problem, otherwise uses platform + default. + Examples: > + :CP next + :CP next --lang python +< + :CP prev [--lang {language}] + Navigate to previous problem in current contest. + Stops at first problem (no wrapping). + --lang: Use specific language for previous problem. + By default, preserves current file's language if + enabled for the new problem, otherwise uses platform + default. + Examples: > + :CP prev + :CP prev --lang cpp +< + :CP {problem_id} [--lang {language}] + Jump to problem {problem_id} in a contest. + Requires that a contest has already been set up. + --lang: Use specific language for this problem. + Examples: > + :CP B + :CP C --lang python +< + + Edit Commands ~ + :CP edit [n] + Open grid test editor showing all test cases. + Tests displayed as 2×N grid (2 rows, N columns): + • Top row: Test inputs (editable) + • Bottom row: Expected outputs (editable) + + Optional [n]: Jump cursor to test n's input buffer + + Changes saved to both cache and disk on exit, + taking effect immediately in :CP run and CLI. + + Keybindings (configurable via |EditConfig|): + q Save all and exit editor + ]t Jump to next test column + [t Jump to previous test column + gd Delete current test column + ga Add new test column at end + Normal window navigation + + Examples: > + :CP edit " Edit all tests + :CP edit 3 " Edit all, start at test 3 +< + + State Restoration ~ + :CP Restore state from current file. + Automatically detects platform, contest, problem, + and language from cached state. Use this after + switching files to restore your CP environment. + + Cache Commands ~ + :CP cache clear [platform] [contest] + Clear cache data at different granularities: + • No args: Clear all cached data + • [platform]: Clear all data for a platform + • [platform] [contest]: Clear specific contest + Examples: > + :CP cache clear + :CP cache clear codeforces + :CP cache clear codeforces 1848 +< + :CP cache read + View the cache in a pretty-printed lua buffer. + Exit with q. + +Template Variables ~ + *cp-template-vars* + Command templates support variable substitution using {variable} syntax: + + • {source} Source file path (e.g. "abc324a.cpp") + • {binary} Output binary path (e.g. "build/abc324a.run" or + "build/abc324a.dbg" for debug builds) + + Example template: > + build = { 'g++', '{source}', '-o', '{binary}', '-std=c++17' } +< Would expand to: > + g++ abc324a.cpp -o build/abc324a.run -std=c++17 +< +Debug Builds ~ + *cp-debug-builds* + The --debug flag uses the debug command configuration instead of build: + + • Normal build: commands.build → outputs to build/.run + • Debug build: commands.debug → outputs to build/.dbg + + Debug builds typically include sanitizers (address, undefined behavior) to + catch memory errors, buffer overflows, and other issues. Both binaries + coexist, so you can switch between normal and debug mode without + recompiling. + + Example debug configuration: > + languages = { + cpp = { + extension = 'cc', + commands = { + build = { 'g++', '-std=c++17', '{source}', '-o', '{binary}' }, + run = { '{binary}' }, + debug = { 'g++', '-std=c++17', '-fsanitize=address,undefined', + '{source}', '-o', '{binary}' }, + } + } + } < -The plugin works automatically with no configuration required. For -customization, see |cp-config|. ============================================================================== CONFIGURATION *cp-config* -Configuration is done via `vim.g.cp`. Set this before using the plugin: +Configuration is done via `vim.g.cp_config`. Set this before using the plugin: >lua - vim.g.cp = { + vim.g.cp_config = { languages = { cpp = { extension = 'cc', @@ -93,7 +235,16 @@ Configuration is done via `vim.g.cp`. Set this before using the plugin: cpp = { extension = 'cpp', commands = { build = { ... } } } }, }, + atcoder = { + enabled_languages = { 'cpp', 'python' }, + default_language = 'cpp', + }, + codeforces = { + enabled_languages = { 'cpp', 'python' }, + default_language = 'cpp', + }, }, + open_url = true, debug = false, ui = { ansi = true, @@ -118,27 +269,23 @@ Configuration is done via `vim.g.cp`. Set this before using the plugin: < By default, C++ (g++ with ISO C++17) and Python are preconfigured under -'languages'. All six platforms are enabled by default. User-supplied -platform entries are merged on top of the defaults — you only need to -specify what you want to change. To disable a platform entirely, set it -to `false`. +'languages'. Platforms select which languages are enabled and which one is +the default; per-platform overrides can tweak 'extension' or 'commands'. -For example, to run Codeforces contests with Python by default and -disable CodeChef: +For example, to run CodeForces contests with Python by default: >lua - vim.g.cp = { + vim.g.cp_config = { platforms = { codeforces = { default_language = 'python', }, - codechef = false, }, } < Any language is supported provided the proper configuration. For example, to -add Rust and use it by default on CSES: +run CSES problems with Rust using the single schema: >lua - vim.g.cp = { + vim.g.cp_config = { languages = { rust = { extension = 'rs', @@ -160,11 +307,8 @@ add Rust and use it by default on CSES: Fields: ~ {languages} (table) Global language registry. Each language provides an {extension} and {commands}. - {platforms} (table) All six platforms - are enabled by default. Each entry is merged on top - of the platform defaults — omitted fields keep their - defaults and unmentioned platforms stay enabled. Set - a platform key to `false` to disable it entirely. + {platforms} (table) Per-platform enablement, + default language, and optional overrides. {hooks} (|cp.Hooks|) Hook functions called at various stages. {debug} (boolean, default: false) Show info messages. {scrapers} (string[]) Supported platform ids. @@ -173,6 +317,8 @@ add Rust and use it by default on CSES: Should return full filename with extension. (default: concatenates contest_id and problem_id, lowercased) {ui} (|CpUI|) UI settings: panel, diff backend, picker. + {open_url} (boolean) Open the contest & problem url in the browser + when the contest is first opened. *CpPlatform* Fields: ~ @@ -249,355 +395,42 @@ add Rust and use it by default on CSES: *cp.Hooks* Fields: ~ - {setup} (|cp.CpSetupHooks|, optional) One-time initialization hooks. - {on} (|cp.CpOnHooks|, optional) Recurring event hooks. + {before_run} (function, optional) Called before test panel opens. + function(state: cp.State) + {before_debug} (function, optional) Called before debug build/run. + function(state: cp.State) + {setup_code} (function, optional) Called after source file is opened. + function(state: cp.State) + {setup_io_input} (function, optional) Called when I/O input buffer created. + function(bufnr: integer, state: cp.State) + Default: helpers.clearcol (removes line numbers/columns) + {setup_io_output} (function, optional) Called when I/O output buffer created. + function(bufnr: integer, state: cp.State) + Default: helpers.clearcol (removes line numbers/columns) - *cp.CpSetupHooks* - Fields: ~ - {contest} (function, optional) Called once when a contest directory - is first created (not on subsequent visits). - function(state: cp.State) - {code} (function, optional) Called after the source buffer is - opened for the first time (guarded by cp_setup_done). - function(state: cp.State) - {io} (|cp.CpSetupIOHooks|, optional) I/O buffer hooks. - - *cp.CpSetupIOHooks* - Fields: ~ - {input} (function, optional) Called when the I/O input buffer is - created. function(bufnr: integer, state: cp.State) - Default: helpers.clearcol - {output} (function, optional) Called when the I/O output buffer is - created. function(bufnr: integer, state: cp.State) - Default: helpers.clearcol - - *cp.CpOnHooks* - Fields: ~ - {enter} (function, optional) Called on every BufEnter on the - solution buffer. Registered as a buffer-scoped autocmd and - fired immediately after setup.code. - function(state: cp.State) - {run} (function, optional) Called before the test panel opens. - function(state: cp.State) - {debug} (function, optional) Called before a debug run. - function(state: cp.State) - - All hook functions receive the cp.nvim state object (|cp.State|). See + Hook functions receive the cp.nvim state object (|cp.State|). See |lua/cp/state.lua| for available methods and fields. + The I/O buffer hooks are called once when the buffers are first created + during problem setup. Use these to customize buffer appearance (e.g., + remove line numbers, set custom options). Access helpers via: +>lua + local helpers = require('cp').helpers +< Example usage: >lua hooks = { - setup = { - contest = function(state) - local dir = vim.fn.fnamemodify( - state.get_source_file(state.get_language()), ':h') - vim.fn.system({ 'cp', '~/.clang-format', dir .. '/.clang-format' }) - end, - code = function(state) - vim.opt_local.foldmethod = 'marker' - vim.diagnostic.enable(false) - end, - }, - on = { - enter = function(state) vim.opt_local.winbar = '' end, - run = function(state) require('config.lsp').format() end, - }, + setup_code = function(state) + print("Setting up " .. state.get_base_name()) + print("Source file: " .. state.get_source_file()) + end, + setup_io_input = function(bufnr, state) + -- Custom setup for input buffer + vim.api.nvim_set_option_value('number', false, { buf = bufnr }) + end } < -============================================================================== -COMMANDS *cp-commands* - -:CP *:CP* - cp.nvim uses a single :CP command with intelligent argument parsing: - - Setup Commands ~ - :CP {platform} {contest_id} [--lang {language}] - Full setup: set platform and load contest metadata. - Scrapes test cases and creates source file. - --lang: Use specific language (default: platform default) - Examples: > - :CP codeforces 1933 - :CP codeforces 1933 --lang python -< - View Commands ~ - :CP run [all|n|n,m,...] [--debug] - Run tests in I/O view (see |cp-io-view|). - Lightweight split showing test verdicts. - - Execution modes: - • :CP run Combined: single execution with all tests - (auto-switches to individual when multiple samples) - • :CP run all Individual: N separate executions - • :CP run n Individual: run test n only - • :CP run n,m,... Individual: run specific tests (e.g. nth and mth) - - --debug: Use debug build (builds to build/.dbg) - - Combined mode runs all test inputs in one execution (matching - platform behavior for multi-test problems). When a problem has - multiple independent sample test cases, :CP run auto-switches to - individual mode to run each sample separately. - - Examples: > - :CP run " Combined: all tests, one execution - :CP run all " Individual: all tests, N executions - :CP run 2 " Individual: test 2 only - :CP run 1,3,5 " Individual: tests 1, 3, and 5 - :CP run all --debug " Individual with debug build -< - :CP panel [--debug] [n] - Open full-screen test panel (see |cp-panel|). - Aggregate table with diff modes for detailed analysis. - Optional [n] focuses on specific test. - --debug: Use debug build (with sanitizers, etc.) - Examples: > - :CP panel " All tests - :CP panel --debug 3 " Test 3, debug build -< - - :CP pick [--lang {language}] - Launch configured picker for interactive - platform/contest selection. - --lang: Pre-select language for chosen contest. - Example: > - :CP pick - :CP pick --lang python -< - - :CP interact [script] - Open an interactive terminal for the current problem. - If an executable interactor is provided, runs the compiled - binary against the source file (see - *cp-interact*). Otherwise, runs the source - file. Only valid for interactive problems. - - :CP stress [generator] [brute] - Start an automated stress test loop against a - brute-force reference. Toggles off if already - running. Without arguments, auto-detects a - generator and brute script in the working - directory. See |cp-stress|. - - Navigation Commands ~ - :CP next [--lang {language}] - Navigate to next problem in current contest. - Stops at last problem (no wrapping). - --lang: Use specific language for next problem. - By default, preserves current file's language if - enabled for the new problem, otherwise uses platform - default. - Examples: > - :CP next - :CP next --lang python -< - :CP prev [--lang {language}] - Navigate to previous problem in current contest. - Stops at first problem (no wrapping). - --lang: Use specific language for previous problem. - By default, preserves current file's language if - enabled for the new problem, otherwise uses platform - default. - Examples: > - :CP prev - :CP prev --lang cpp -< - :CP {problem_id} [--lang {language}] - Jump to problem {problem_id} in a contest. - Requires that a contest has already been set up. - --lang: Use specific language for this problem. - Examples: > - :CP B - :CP C --lang python -< - - Edit Commands ~ - :CP edit [n] - Open grid test editor showing all test cases. - Tests displayed as 2×N grid (2 rows, N columns): - • Top row: Test inputs (editable) - • Bottom row: Expected outputs (editable) - - Optional [n]: Jump cursor to test n's input buffer - - Changes saved to both cache and disk on exit, - taking effect immediately in :CP run and CLI. - - Keybindings (configurable via |EditConfig|): - q Save all and exit editor - ]t Jump to next test column - [t Jump to previous test column - gd Delete current test column - ga Add new test column at end - Normal window navigation - - Examples: > - :CP edit " Edit all tests - :CP edit 3 " Edit all, start at test 3 -< - - Race Commands ~ - :CP {platform} {contest_id} --race [--lang {language}] - Start a countdown to the contest's scheduled - start time. At T=0, automatically runs: - :CP {platform} {contest_id} [--lang ...] - Examples: > - :CP atcoder abc400 --race - :CP codeforces 2100 --race --lang python -< - Credential Commands ~ - :CP login [platform] - Set or update stored credentials for a platform. - Prompts for username and password, overwriting - any previously saved credentials. - If [platform] is omitted, uses the active platform. - Examples: > - :CP login atcoder - :CP login codeforces -< - :CP logout [platform] - Remove stored credentials for a platform. - If [platform] is omitted, uses the active platform. - Examples: > - :CP logout atcoder -< - :CP {platform} signup - Open the platform's registration page in the - browser via |vim.ui.open|. Works even if - {platform} is not enabled in your config. - Examples: > - :CP atcoder signup - :CP codeforces signup -< - Submit Commands ~ - :CP submit [--lang {language}] - Submit the current solution to the online - judge. Uses stored credentials (set via - :CP login). Prompts on first use if no - credentials are saved. - --lang: Submit solution for a specific language. - - :CP open [problem|contest|standings] - Open the URL for the current problem, contest, - or standings page in the browser via - |vim.ui.open|. Defaults to "problem" if no - argument is given. Warns if the URL is not - available (e.g. CSES has no standings). - Examples: > - :CP open - :CP open contest - :CP open standings -< - State Restoration ~ - :CP Restore state from current file. - Automatically detects platform, contest, problem, - and language from cached state. Use this after - switching files to restore your CP environment. - - Cache Commands ~ - :CP cache clear [platform] [contest] - Clear cache data at different granularities: - • No args: Clear all cached data - • [platform]: Clear all data for a platform - • [platform] [contest]: Clear specific contest - Examples: > - :CP cache clear - :CP cache clear codeforces - :CP cache clear codeforces 1848 -< - :CP cache read - View the cache in a pretty-printed lua buffer. - Exit with q. - -Template Variables ~ - *cp-template-vars* - Command templates support variable substitution using {variable} syntax: - - • {source} Source file path (e.g. "abc324a.cpp") - • {binary} Output binary path (e.g. "build/abc324a.run" or - "build/abc324a.dbg" for debug builds) - - Example template: > - build = { 'g++', '{source}', '-o', '{binary}', '-std=c++17' } -< Would expand to: > - g++ abc324a.cpp -o build/abc324a.run -std=c++17 -< -Debug Builds ~ - *cp-debug-builds* - The --debug flag uses the debug command configuration instead of build: - - • Normal build: commands.build → outputs to build/.run - • Debug build: commands.debug → outputs to build/.dbg - - Debug builds typically include sanitizers (address, undefined behavior) to - catch memory errors, buffer overflows, and other issues. Both binaries - coexist, so you can switch between normal and debug mode without - recompiling. - - Example debug configuration: > - languages = { - cpp = { - extension = 'cc', - commands = { - build = { 'g++', '-std=c++17', '{source}', '-o', '{binary}' }, - run = { '{binary}' }, - debug = { 'g++', '-std=c++17', '-fsanitize=address,undefined', - '{source}', '-o', '{binary}' }, - } - } - } -< - -============================================================================== -MAPPINGS *cp-mappings* - -cp.nvim provides mappings for all primary actions. These dispatch -through the same code path as |:CP|. - - *(cp-run)* -(cp-run) Run tests in I/O view. Equivalent to :CP run. - - *(cp-panel)* -(cp-panel) Open full-screen test panel. Equivalent to :CP panel. - - *(cp-edit)* -(cp-edit) Open the test case editor. Equivalent to :CP edit. - - *(cp-next)* -(cp-next) Navigate to the next problem. Equivalent to :CP next. - - *(cp-prev)* -(cp-prev) Navigate to the previous problem. Equivalent to :CP prev. - - *(cp-pick)* -(cp-pick) Launch the contest picker. Equivalent to :CP pick. - - *(cp-interact)* -(cp-interact) Open interactive mode. Equivalent to :CP interact. - - *(cp-stress)* -(cp-stress) Run stress test loop. Equivalent to :CP stress. - - *(cp-submit)* -(cp-submit) Submit current solution. Equivalent to :CP submit. - - *(cp-open)* -(cp-open) Open current problem URL in browser. Equivalent to :CP open. - -Example configuration: >lua - vim.keymap.set('n', 'cr', '(cp-run)') - vim.keymap.set('n', 'cp', '(cp-panel)') - vim.keymap.set('n', 'ce', '(cp-edit)') - vim.keymap.set('n', 'cn', '(cp-next)') - vim.keymap.set('n', 'cN', '(cp-prev)') - vim.keymap.set('n', 'cc', '(cp-pick)') - vim.keymap.set('n', 'ci', '(cp-interact)') - vim.keymap.set('n', 'cs', '(cp-stress)') - vim.keymap.set('n', 'cu', '(cp-submit)') - -< - ============================================================================== LANGUAGE SELECTION *cp-lang-selection* @@ -675,41 +508,6 @@ URL format: https://cses.fi/problemset/task/{problem_id} Usage examples: > :CP cses dynamic_programming " Set up all problems in dp category -CodeChef ~ - *cp-codechef* -URL format: https://www.codechef.com/{contest_id}/problems/{problem_id} - -The contest_id is the contest code from the URL (e.g. START209). - -Usage examples: > - :CP codechef START209 " Set up codechef.com/START209 - -USACO ~ - *cp-usaco* -URL format: https://usaco.org/index.php?page=viewproblem2&cpid={cpid} - -The contest_id combines the abbreviated month, two-digit year, and division -in lowercase, joined by underscores (e.g. dec24_gold, feb23_silver). - -Usage examples: > - :CP usaco dec24_gold " Set up December 2024 Gold division - :CP usaco feb23_silver " Set up February 2023 Silver division - -Kattis ~ - *cp-kattis* -Kattis supports single-problem and full-contest modes. - -Single problem — the contest_id is the problem slug from the URL: -URL format: https://open.kattis.com/problems/{slug} - -Full contest — the contest_id is the contest ID from the URL. All problems -are set up at once with :CP next/:CP prev navigation: -URL format: https://open.kattis.com/contests/{id} - -Usage examples: > - :CP kattis primesieve " Single problem - :CP kattis t8tnpe " Full contest (all problems, A–H navigation) - ============================================================================== COMPLETE WORKFLOW EXAMPLE *cp-example* @@ -744,9 +542,7 @@ Example: Setting up and solving AtCoder contest ABC324 :CP < Automatically restores abc323 contest context -8. Submit solution: > - :CP submit -< Uses stored credentials and submits to AtCoder. +8. Submit solutions on AtCoder website ============================================================================== I/O VIEW *cp-io-view* @@ -816,9 +612,9 @@ While in the I/O view buffers, use the configured keymaps to cycle through tests Buffer Customization ~ -Use the hooks.setup.io.input and hooks.setup.io.output hooks (see |cp.Hooks|) -to customize buffer appearance. By default, line numbers and columns are -removed via helpers.clearcol (see |cp-helpers|). +Use the setup_io_input and setup_io_output hooks (see |cp.Hooks|) to customize +buffer appearance. By default, line numbers and columns are removed via +helpers.clearcol (see |cp-helpers|). ============================================================================== VERDICT FORMATTING *cp-verdict-format* @@ -957,144 +753,6 @@ When using :CP interact {interactor}, the interactor must be executable Keymaps ~ Close the terminal and restore the previous layout. -============================================================================== -STRESS TESTING *cp-stress* - -Start an automated stress test loop to find inputs where your solution -disagrees with a brute-force reference. - -:CP stress [generator] [brute] - Start the stress loop. Toggles off if the loop is already running. - {generator} Generator script path (default: auto-detected). - {brute} Brute-force solution path (default: auto-detected). - Auto-detection looks for files named gen.* and brute.* in the CWD. - - The stress panel opens and streams results for each iteration. - On a mismatch, the failing input is displayed in the panel. - -Keymaps ~ - Close the stress panel and restore the previous layout. - -============================================================================== -RACE *cp-race* - -Count down to a contest's start time and automatically run setup at T=0. - -:CP {platform} {contest_id} --race [--lang {language}] - Start a countdown timer. At T=0, automatically runs: - :CP {platform} {contest_id} [--lang {language}] - Examples: > - :CP atcoder abc400 --race - :CP codeforces 2100 --race --lang python -< -Starting a new race while one is active automatically cancels the previous one. - -Statusline integration: see |cp-race-status|. - -============================================================================== -CREDENTIALS *cp-credentials* - -Manage stored login credentials for platform submission. - -Credentials are stored under _credentials in the main cache file -(stdpath('data')/cp-nvim.json). Use :CP cache read to inspect them. - -:CP login [platform] - Set or update credentials for a platform. Prompts for username - and password, overwriting any previously saved values. - Omit [platform] to use the currently active platform. - -:CP logout [platform] - Remove stored credentials for a platform. - Omit [platform] to use the currently active platform. - -:CP {platform} signup - Open the platform's account registration page in the browser via - |vim.ui.open|. Works even if {platform} is not enabled in your - config. {platform} is one of: atcoder, codechef, codeforces, cses, - kattis, usaco. - -============================================================================== -SUBMIT *cp-submit* - -Submit the current solution to the online judge. - -:CP submit [--lang {language}] - Submit the current solution. Uses stored credentials (set via - :CP login). Prompts on first use if no credentials are saved. - --lang: Override the language to submit. - - Platform support: - AtCoder Fully implemented. - Codeforces Fully implemented. - CSES Fully implemented. - Kattis Fully implemented. - USACO Fully implemented. - CodeChef Not yet implemented. - - See |cp-submit-language| for configuring the language version - (e.g. C++20 instead of C++17). - -============================================================================== -SUBMIT LANGUAGE VERSIONS *cp-submit-language* - -When submitting, cp.nvim selects a language version for the platform. -The default is C++17 for cpp and Python 3 for python. - -Configuring a version ~ - -Set {version} globally or per-platform: ->lua - languages = { - cpp = { version = "c++20", ... }, - }, - platforms = { - atcoder = { - overrides = { cpp = { version = "c++23" } }, - }, - }, -< -Available versions per platform ~ - - Platform cpp python - AtCoder c++23 python3 - Codeforces c++17 python3 - CSES c++17 python3 - Kattis c++17/20/23 python3 - USACO c++17/20/23 python3 - CodeChef c++17 python3 - -Using a raw platform ID ~ - -If your preferred version is not listed, you can bypass version -lookup by setting {submit_id} to the raw platform language ID: ->lua - platforms = { - codeforces = { - overrides = { cpp = { submit_id = "91" } }, - }, - }, -< -To find the raw ID, open the platform's submit page in your browser, -inspect the language dropdown, and copy the