*cp.txt* Competitive programming plugin for Neovim Author: Barrett Ruth License: Same terms as Vim itself (see |license|) INTRODUCTION *cp* *cp.nvim* cp.nvim is a competitive programming plugin that automates problem setup, compilation, and testing workflow for online judges. Supported platforms: AtCoder, Codeforces, CSES Supported languages: C++, Python REQUIREMENTS *cp-requirements* - Neovim 0.10.0+ - uv package manager (https://docs.astral.sh/uv/) - Language runtime/compiler (g++, python3) Optional: - LuaSnip for template expansion (https://github.com/L3MON4D3/LuaSnip) COMMANDS *cp-commands* *:CP* cp.nvim uses a single :CP command with intelligent argument parsing: Setup Commands ~ :CP {platform} {contest_id} {problem_id} [--lang={language}] Full setup: set platform, load contest metadata, and set up specific problem. Scrapes test cases and creates source file. Example: :CP codeforces 1933 a Example: :CP codeforces 1933 a --lang=python :CP {platform} {contest_id} Contest setup: set platform and load contest metadata for navigation. Caches problem list. Example: :CP atcoder abc324 :CP {platform} Platform setup: set platform only. Example: :CP cses :CP {problem_id} [--lang={language}] Problem switch: switch to different problem within current contest context. Example: :CP b (switch to problem b) Example: :CP b --lang=python Action Commands ~ :CP run Compile and run current problem with test input. Shows execution time and output comparison. :CP debug Compile with debug flags and run current problem. Includes sanitizers and debug symbols. :CP diff Enter diff mode to compare actual vs expected output. Run again to exit diff mode. Navigation Commands ~ :CP next Navigate to next problem in current contest. Stops at last problem (no wrapping). :CP prev Navigate to previous problem in current contest. Stops at first problem (no wrapping). CONFIGURATION *cp-config* cp.nvim works out of the box. No setup required. Optional configuration with lazy.nvim: > { 'barrett-ruth/cp.nvim', cmd = 'CP', opts = { debug = false, contests = { default = { cpp = { compile = { 'g++', '-std=c++{version}', '-O2', '-Wall', '-Wextra', '-DLOCAL', '{source}', '-o', '{binary}', }, run = { '{binary}' }, debug = { 'g++', '-std=c++{version}', '-g3', '-fsanitize=address,undefined', '-DLOCAL', '{source}', '-o', '{binary}', }, version = 20, extension = "cc", }, python = { run = { 'python3', '{source}' }, debug = { 'python3', '{source}' }, extension = "py", }, timeout_ms = 2000, }, codeforces = { cpp = { version = 23 } }, }, hooks = { before_run = function(ctx) vim.cmd.w() end, before_debug = function(ctx) -- ctx.problem_id, ctx.platform, ctx.source_file, etc. vim.cmd.w() end, }, snippets = { ... }, -- LuaSnip snippets tile = function(source_buf, input_buf, output_buf) ... end, filename = function(contest, problem_id, problem_letter) ... end, } } < Configuration options: contests Dictionary of contest configurations - each contest inherits from 'default'. cpp C++ language configuration compile Compile command template with {version}, {source}, {binary} placeholders run Run command template with {binary} placeholder debug Debug compile command template version C++ standard version (e.g. 20, 23) extension File extension for C++ files (default: "cc") python Python language configuration run Run command template with {source} placeholder debug Debug run command template extension File extension for Python files (default: "py") default_language Default language when --lang not specified (default: "cpp") timeout_ms Duration (ms) to run/debug before timeout snippets LuaSnip snippets by contest type hooks Functions called at specific events before_run Called before :CP run function(ctx) ctx contains: - problem_id: string - platform: string (atcoder/codeforces/cses) - contest_id: string - source_file: string (path to source) - input_file: string (path to .cpin) - output_file: string (path to .cpout) - expected_file: string (path to .expected) - contest_config: table (language configs) (default: nil, do nothing) before_debug Called before :CP debug function(ctx) Same ctx as before_run (default: nil, do nothing) debug Show info messages during operation (default: false, silent operation) tile Custom function to arrange windows function(source_buf, input_buf, output_buf) (default: nil, uses built-in layout) filename Custom function to generate filenames function(contest, problem_id, problem_letter) (default: nil, uses problem_id + letter + ".cc") WORKFLOW *cp-workflow* For the sake of consistency and simplicity, cp.nvim extracts contest/problem identifiers from URLs. This means that, for example, CodeForces/AtCoder contests are configured by their round id rather than round number. See below. PLATFORM-SPECIFIC USAGE *cp-platforms* AtCoder ~ *cp-atcoder* URL format: https://atcoder.jp/contests/abc123/tasks/abc123_a In terms of cp.nvim, this corresponds to: - Platform: atcoder - Contest ID: abc123 - Problem ID: a Usage examples: > :CP atcoder abc123 a " Full setup: problem A from contest ABC123 :CP atcoder abc123 " Contest setup: load contest metadata only :CP b " Switch to problem B (if contest loaded) :CP next " Navigate to next problem in contest < Codeforces ~ *cp-codeforces* URL format: https://codeforces.com/contest/1234/problem/A In terms of cp.nvim, this corresponds to: - Platform: codeforces - Contest ID: 1234 - Problem ID: a (lowercase) Usage examples: > :CP codeforces 1934 a " Full setup: problem A from contest 1934 :CP codeforces 1934 " Contest setup: load contest metadata only :CP c " Switch to problem C (if contest loaded) :CP prev " Navigate to previous problem in contest < CSES ~ *cp-cses* URL format: https://cses.fi/problemset/task/1068 CSES is organized by categories rather than contests. Currently all problems are grouped under "CSES Problem Set" category. In terms of cp.nvim, this corresponds to: - Platform: cses - Contest ID: "CSES Problem Set" (category) - Problem ID: 1068 (numeric) Usage examples: > :CP cses 1068 " Set up problem 1068 from CSES :CP 1070 " Switch to problem 1070 (if CSES loaded) :CP next " Navigate to next problem in CSES < COMPLETE WORKFLOW EXAMPLE *cp-example* Example: Setting up and solving AtCoder contest ABC324 1. Browse to https://atcoder.jp/contests/abc324 2. Set up contest and load metadata: > :CP atcoder abc324 < This caches all problems (A, B, C, D, E, F, G) for navigation 3. Start with problem A: > :CP a < This creates abc324a.cc and scrapes test cases 4. Code your solution, then test: > :CP run < 5. If needed, debug: > :CP debug < 6. Compare output visually: > :CP diff < 7. Move to next problem: > :CP next < This automatically sets up problem B 8. Continue solving problems with :CP next/:CP prev navigation 9. Submit solutions on AtCoder website Example: Quick setup for single Codeforces problem > :CP codeforces 1933 a " One command setup :CP run " Test immediately < FILE STRUCTURE *cp-files* cp.nvim creates the following file structure upon problem setup: {contest_id}{problem_id}.cc " Source file (e.g. abc324a.cc) build/ {contest_id}{problem_id}.run " Compiled binary io/ {contest_id}{problem_id}.cpin " Test input {contest_id}{problem_id}.cpout " Program output {contest_id}{problem_id}.expected " Expected output The plugin automatically manages this structure and navigation between problems maintains proper file associations. SNIPPETS *cp-snippets* cp.nvim integrates with LuaSnip for automatic template expansion. When you open a new problem file, type the contest name and press to expand. Built-in snippets include basic C++ and Python templates for each contest type. Custom snippets can be added via configuration. IMPORTANT: Snippet trigger names must exactly match the contest/platform names: - "codeforces" for Codeforces problems - "atcoder" for AtCoder problems - "cses" for CSES problems The plugin automatically selects the appropriate template based on the file extension (e.g., .cc files get C++ templates, .py files get Python templates). HEALTH CHECK *cp-health* Run |:checkhealth| cp to verify your setup. vim:tw=78:ts=8:ft=help:norl: