*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 REQUIREMENTS *cp-requirements* - Neovim 0.10.0+ - uv package manager (https://docs.astral.sh/uv/) - C++ compiler (g++/clang++) Optional: - LuaSnip for template expansion (https://github.com/L3MON4D3/LuaSnip) COMMANDS *cp-commands* *:CP* :CP {contest} Set up contest environment for {contest}. Available contests: atcoder, codeforces, cses :CP {contest} {contest_id} {problem_letter?} Set up problem from {contest}. Extract contest_id and problem_letter (optional) from the problem URL. Scrapes test cases and creates source file. :CP {contest_id} {problem_letter} Set up problem in current contest mode. Requires contest to be set first with :CP {contest} :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. CONFIGURATION *cp-config* cp.nvim is automatically lazy-loaded - no config/setup is required. Provide extra options via a setup() function with your package manager. For example, with lazy.nvim (https://github.com/folke/lazy.nvim): { 'barrett-ruth/cp.nvim', config = function() local ls = require('luasnip') local s = ls.snippet require('cp').setup({ debug = false, contests = { default = { cpp_version = 20, compile_flags = { "-O2", "-DLOCAL", "-Wall", "-Wextra" }, debug_flags = { "-g3", "-fsanitize=address,undefined", "-DLOCAL" }, timeout_ms = 2000, }, atcoder = { cpp_version = 23, }, }, snippets = { cses = { s("cses", "#include \nusing namespace std;\n\nint main() {\n\t$0\n}") }, }, hooks = { before_run = function(problem_id) vim.cmd.w() vim.lsp.buf.format() end, before_debug = function(problem_id) ... end }, tile = function(source_buf, input_buf, output_buf) vim.api.nvim_set_current_buf(source_buf) vim.cmd.vsplit() vim.api.nvim_set_current_buf(output_buf) vim.cmd.vsplit() vim.api.nvim_set_current_buf(input_buf) vim.cmd('wincmd h | wincmd h') end, filename = function(contest, problem_id, problem_letter) if contest == "atcoder" then return problem_id:lower() .. (problem_letter or "") .. ".cpp" else return problem_id:lower() .. (problem_letter or "") .. ".cc" end end, }) end } Configuration options: contests Dictionary of contest configurations - each contest inherits from 'default'. cpp_version c++ standard version (e.g. 20, 23) compile_flags compiler flags for run builds debug_flags compiler flags for debug builds 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(problem_id) (default: nil, do nothing) before_debug Called before :CP debug function(problem_id) (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: - Contest ID: abc123 - Problem letter: a Usage examples: > :CP atcoder abc123 a " Set up problem A from contest ABC123 :CP atcoder " Set up AtCoder contest mode first :CP abc123 a " Then set up problem (if contest mode is set) < Codeforces ~ *cp-codeforces* URL format: https://codeforces.com/contest/1234/problem/A In terms of cp.nvim, this corresponds to: - Contest ID: 1234 - Problem letter: A Usage examples: > :CP codeforces 1234 a " Set up problem A from contest id 1234 :CP codeforces " Set up Codeforces contest mode first :CP 1234 a " Then set up problem (if contest mode is set) < CSES ~ *cp-cses* URL format: https://cses.fi/problemset/task/1068 In terms of cp.nvim, this corresponds to: - Problem ID: 1068 Usage examples: > :CP cses 1068 " Set up problem 1068 :CP cses " Set up CSES contest mode first :CP 1068 " Then set up problem (if contest mode is set) < COMPLETE WORKFLOW EXAMPLE *cp-example* Example: Setting up AtCoder problem ABC123-A 1. Browse to https://atcoder.jp/contests/abc123/tasks/abc123_a 2. Read the problem statement on the website 3. In Neovim, extract identifiers and set up :CP atcoder abc123 a < This creates abc123a.cc (or however you've configured the filename in *cp-setup*) and scrapes test cases 4. Code and test :CP run 5. Debug :CP debug 6. Test: > :CP diff 7. Submit remote on AtCoder FILE STRUCTURE *cp-files* cp.nvim creates the following file structure upon setup: problem.cc build/*.{run,debug} io/ problem.in problem.out problem.expected 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++ templates for each contest type. Custom snippets can be added via configuration. HEALTH CHECK *cp-health* Run |:checkhealth| cp to verify your setup. vim:tw=78:ts=8:ft=help:norl: