cp.nvim/doc/cp.nvim.txt

598 lines
27 KiB
Text

*cp.nvim.txt* Competitive programming plugin for Neovim
Author: Barrett Ruth <br.barrettruth@gmail.com>
License: Same terms as Vim itself (see |license|)
==============================================================================
INTRODUCTION *cp.nvim*
cp.nvim is a competitive programming plugin that automates problem setup,
compilation, and testing workflow for online judges.
Supported platforms (for now!): AtCoder, Codeforces, CSES
==============================================================================
REQUIREMENTS *cp-requirements*
- Neovim 0.10.0+
- Unix-like operating system
Optional:
- uv package manager (https://docs.astral.sh/uv/)
- LuaSnip for template expansion (https://github.com/L3MON4D3/LuaSnip)
==============================================================================
COMMANDS *cp-commands*
:CP *:CP*
cp.nvim uses a single :CP command with intelligent argument parsing:
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.
Requires previous setup with full :CP command.
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
:CP codeforces 1933 a --lang=python
<
:CP {platform} {contest_id}
Contest setup: set platform, load contest metadata,
and scrape ALL problems in the contest. This creates
source files for every problem and caches all test
cases for efficient bulk setup. Opens the first
problem after completion.
Example: >
:CP atcoder abc324
:CP codeforces 1951
<
: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
:CP b --lang=python
<
Action Commands ~
:CP run [--debug] Toggle run panel for individual test case
debugging. Shows per-test results with redesigned
layout for efficient comparison.
Use --debug flag to compile with debug flags.
Requires contest setup first.
:CP pick Launch configured picker for interactive
platform/contest/problem selection.
Navigation Commands ~
:CP next Navigate to next problem in current contest.
Stops at last problem (no wrapping).
Navigation Commands ~
:CP prev Navigate to previous problem in current contest.
Stops at first problem (no wrapping).
Command Flags ~
*cp-flags*
Flags can be used with setup and action commands:
--lang={language} Specify language for the problem.
--lang {language} Alternative syntax for language specification.
Supported languages: cpp, python
Example: >
:CP atcoder abc324 a --lang=python
:CP b --lang cpp
<
--debug Enable debug compilation with additional flags.
Uses the `debug` command template instead of
`compile`. Typically includes debug symbols and
sanitizers for memory error detection.
Example: >
:CP run --debug
<
Note: Debug compilation may be slower but provides
better error reporting for runtime issues.
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")
• {contest} Contest identifier (e.g. "abc324", "1933")
• {problem} Problem identifier (e.g. "a", "b")
Example template: >
compile = { 'g++', '{source}', '-o', '{binary}', '-std=c++17' }
< Would expand to: >
g++ abc324a.cpp -o build/abc324a.run -std=c++17
<
==============================================================================
CONFIGURATION *cp-config*
Here's an example configuration with lazy.nvim: >lua
{
'barrett-ruth/cp.nvim',
cmd = 'CP',
opts = {
contests = {
default = {
cpp = {
compile = { 'g++', '{source}', '-o', '{binary}',
'-std=c++17', '-fdiagnostic-colors=always' },
test = { '{binary}' },
debug = { 'g++', '{source}', '-o', '{binary}',
'-std=c++17', '-g',
'-fdiagnostic-colors=always'
'-fsanitize=address,undefined' },
},
python = {
test = { 'python3', '{source}' },
},
},
},
snippets = {},
debug = false,
scrapers = { 'atcoder', 'codeforces', 'cses' },
run_panel = {
ansi = true,
diff_mode = 'vim',
next_test_key = '<c-n>',
prev_test_key = '<c-p>',
toggle_diff_key = '<c-q>',
max_output_lines = 50,
},
diff = {
git = {
args = { 'diff', '--no-index', '--word-diff=plain',
'--word-diff-regex=.', '--no-prefix' },
},
},
picker = 'telescope', -- 'telescope', 'fzf-lua', or nil (disabled)
}
}
<
By default, all contests are configured to use C++ with the g++ compiler and ISO standard
17. Python is also configured with the system executable python as a non-default option. Consult lua/cp/config.lua for
more information.
For example, to run CodeForces contests with Python, only the following config
is required:
{
contests = {
codeforces = {
default_langauge = 'python'
}
}
}
*cp.Config*
Fields: ~
{contests} (table<string,ContestConfig>) Contest configurations.
{hooks} (|cp.Hooks|) Hook functions called at various stages.
{snippets} (table[]) LuaSnip snippet definitions.
{debug} (boolean, default: false) Show info messages
during operation.
{scrapers} (table<string>) List of enabled scrapers.
Default: all scrapers enabled
{run_panel} (|RunPanelConfig|) Test panel behavior configuration.
{diff} (|DiffConfig|) Diff backend configuration.
{picker} (string, optional) Picker integration: "telescope",
"fzf-lua", or nil to disable. When enabled, provides
:CP pick for interactive platform/contest/problem selection.
{filename} (function, optional) Custom filename generation.
function(contest, contest_id, problem_id, config, language)
Should return full filename with extension.
(default: concatenates contest_id and problem_id, lowercased)
*cp.ContestConfig*
Fields: ~
{cpp} (|LanguageConfig|) C++ language configuration.
{python} (|LanguageConfig|) Python language configuration.
{default_language} (string, default: "cpp") Default language when
--lang not specified.
*cp.LanguageConfig*
Fields: ~
{compile} (string[], optional) Compile command template with
{source}, {binary} placeholders.
{test} (string[]) Test execution command template.
{debug} (string[], optional) Debug compile command template.
{extension} (string) File extension (e.g. "cc", "py").
{executable} (string, optional) Executable name for interpreted languages.
*cp.RunPanelConfig*
Fields: ~
{ansi} (boolean, default: true) Enable ANSI color parsing and
highlighting. When true, compiler output and test results
display with colored syntax highlighting. When false,
ANSI escape codes are stripped for plain text display.
Requires vim.g.terminal_color_* to be configured for
proper color display.
{diff_mode} (string, default: "none") Diff backend: "none", "vim", or "git".
"none" displays plain buffers without highlighting,
"vim" uses built-in diff, "git" provides character-level precision.
{next_test_key} (string, default: "<c-n>") Key to navigate to next test case.
{prev_test_key} (string, default: "<c-p>") Key to navigate to previous test case.
{toggle_diff_key} (string, default: "<c-t>") Key to cycle through diff modes.
{close_key} (string, default: "<c-q>") Close the run panel/interactive terminal
{max_output_lines} (number, default: 50) Maximum lines of test output.
*cp.DiffConfig*
Fields: ~
{git} (|cp.DiffGitConfig|) Git diff backend configuration.
*cp.DiffGitConfig*
Fields: ~
{args} (string[]) Command-line arguments for git diff.
Default: { 'diff', '--no-index', '--word-diff=plain',
'--word-diff-regex=.', '--no-prefix' }
• --no-index: Compare files outside git repository
• --word-diff=plain: Character-level diff markers
• --word-diff-regex=.: Split on every character
• --no-prefix: Remove a/ b/ prefixes from output
*cp.Hooks*
Fields: ~
{before_run} (function, optional) Called before test panel opens.
function(state: cp.State)
{before_debug} (function, optional) Called before debug compilation.
function(state: cp.State)
{setup_code} (function, optional) Called after source file is opened.
Good for configuring buffer settings.
function(state: cp.State)
Hook functions receive the cp.nvim state object (cp.State). See the state
module documentation (lua/cp/state.lua) for available methods and fields.
Example usage in hook: >lua
hooks = {
setup_code = function(state)
print("Setting up " .. state.get_base_name())
print("Source file: " .. state.get_source_file())
end
}
<
==============================================================================
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
Usage examples: >
:CP atcoder abc324 a " Full setup: problem A from contest ABC324
:CP atcoder abc324 " Contest setup: load contest metadata only
:CP b " Switch to problem B (if contest loaded)
:CP next " Navigate to next problem in contest
<
Note: AtCoder template includes optimizations
for multi-test case problems commonly found
in contests.
AtCoder Heuristic Contests (AHC) are excluded
from the contest list as they don't have
standard sample test cases.
Codeforces ~
*cp-codeforces*
URL format: https://codeforces.com/contest/1234/problem/A
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
<
Note: Problem IDs are automatically converted
to lowercase for consistency.
CSES ~
*cp-cses*
URL format: https://cses.fi/problemset/task/1068
Usage examples: >
:CP cses dynamic_programming 1633 " Set up problem 1633 from DP category
:CP cses dynamic_programming " Set up ALL problems from DP category
<
Note: Category name is always required. For bulk
setup, omit the problem ID to scrape all problems
in the category.
==============================================================================
COMPLETE WORKFLOW EXAMPLE *cp-example*
Example: Setting up and solving AtCoder contest ABC324
1. Browse to https://atcoder.jp/contests/abc324
2. Set up entire contest (bulk setup): >
:CP atcoder abc324
< This scrapes ALL problems (A, B, C, D, ...), creates source files
for each, downloads all test cases, and opens problem A.
3. Alternative: Set up single problem: >
:CP atcoder abc324 a
< This creates only a.cc and scrapes its test cases
4. Code your solution, then test: >
:CP run
< Navigate with j/k, run specific tests with <enter>
Exit test panel with q or :CP run when done
5. If needed, debug with sanitizers: >
:CP run --debug
<
6. Move to next problem: >
:CP next
< This automatically sets up problem B
7. Continue solving problems with :CP next/:CP prev navigation
8. Switch to another file (e.g. previous contest): >
:e ~/contests/abc323/a.cpp
:CP
< Automatically restores abc323 contest context
9. Submit solutions on AtCoder website
==============================================================================
PICKER INTEGRATION *cp-picker*
When picker integration is enabled in configuration, cp.nvim provides interactive
platform and contest selection using telescope.nvim or fzf-lua.
:CP pick *:CP-pick*
Launch configured picker for interactive problem selection.
Control Flow: Select Platform → Contest → Code!
Requires picker = 'telescope' or picker = 'fzf-lua' in configuration.
Requires corresponding plugin (telescope.nvim or fzf-lua) to be installed.
PICKER KEYMAPS *cp-picker-keys*
<c-r> Force refresh contest list, bypassing cache.
Useful when contest lists are outdated or incomplete
==============================================================================
RUN PANEL *cp-run*
The run panel provides individual test case debugging with a streamlined
layout optimized for modern screens. Shows test status with competitive
programming terminology and efficient space usage.
Activation ~
*:CP-run*
:CP run [--debug] Toggle run panel on/off. When activated,
replaces current layout with test interface.
Automatically compiles and runs all tests.
Use --debug flag to compile with debug symbols
and sanitizers. Toggle again to restore original
layout.
Interface ~
The run panel uses the following table layout: >
┌─────┬────────┬──────────────┬───────────┬──────────┬─────────────┐
│ # │ Status │ Runtime (ms) │ Time (ms) │ Mem (MB) │ Exit Code │
├─────┼────────┼──────────────┼───────────┼──────────┼─────────────┤
│ 1 │ AC │ 12.0 │ 2000 │ 256 │ 0 │
│> 2 │ WA │ 45.70 │ 2000 │ 256 │ 1 │
├─────┴────────┴──────────────┴───────────┴──────────┴─────────────┤
│Input: │
│5 3 │
├─────┬────────┬──────────────┬───────────┬──────────┬─────────────┤
│ 3 │ AC │ 9.0 │ 2000 │ 256 │ 0 │
│ 4 │ RTE │ 0.0 │ 2000 │ 256 │139 (SIGUSR2)│
└─────┴────────┴──────────────┴───────────┴──────────┴─────────────┘
┌──────────────────────────────────────────────────────────────────┐
│Expected vs Actual │
│423 │
│100 │
│hello world │
└──────────────────────────────────────────────────────────────────┘
Status Indicators ~
Test cases use competitive programming terminology with color highlighting:
AC Accepted (passed) - Green
WA Wrong Answer (output mismatch) - Red
TLE Time Limit Exceeded (timeout) - Orange
RTE Runtime Error (non-zero exit) - Purple
<
==============================================================================
ANSI COLORS AND HIGHLIGHTING *cp-ansi*
cp.nvim provides comprehensive ANSI color support and highlighting for
compiler output, program stderr, and diff visualization.
==============================================================================
HIGHLIGHT GROUPS *cp-highlights*
Test Status Groups ~
Test cases use competitive programming terminology with color highlighting:
CpTestAC Green foreground for AC status
CpTestWA Red foreground for WA status
CpTestTLE Orange foreground for TLE status
CpTestRTE Purple foreground for RTE status
CpTestPending Gray foreground for pending tests
ANSI Color Groups ~
cp.nvim preserves ANSI colors from compiler output and program stderr using
a sophisticated parsing system. Colors are automatically mapped to your
terminal colorscheme via vim.g.terminal_color_* variables.
Basic formatting groups:
CpAnsiBold Bold text formatting
CpAnsiItalic Italic text formatting
CpAnsiBoldItalic Combined bold and italic formatting
Standard terminal colors (each supports Bold, Italic, BoldItalic variants):
CpAnsiRed Standard red (terminal_color_1)
CpAnsiGreen Standard green (terminal_color_2)
CpAnsiYellow Standard yellow (terminal_color_3)
CpAnsiBlue Standard blue (terminal_color_4)
CpAnsiMagenta Standard magenta (terminal_color_5)
CpAnsiCyan Standard cyan (terminal_color_6)
CpAnsiWhite Standard white (terminal_color_7)
CpAnsiBlack Standard black (terminal_color_0)
Bright color variants:
CpAnsiBrightRed Bright red (terminal_color_9)
CpAnsiBrightGreen Bright green (terminal_color_10)
CpAnsiBrightYellow Bright yellow (terminal_color_11)
CpAnsiBrightBlue Bright blue (terminal_color_12)
CpAnsiBrightMagenta Bright magenta (terminal_color_13)
CpAnsiBrightCyan Bright cyan (terminal_color_14)
CpAnsiBrightWhite Bright white (terminal_color_15)
CpAnsiBrightBlack Bright black (terminal_color_8)
Example combinations:
CpAnsiBoldRed Bold red combination
CpAnsiItalicGreen Italic green combination
CpAnsiBoldItalicYellow Bold italic yellow combination
Diff Highlighting ~
Diff visualization uses Neovim's built-in highlight groups that automatically
adapt to your colorscheme:
DiffAdd Highlights added text in git diffs
DiffDelete Highlights removed text in git diffs
These groups are automatically used by the git diff backend for character-level
difference visualization with optimal colorscheme integration.
==============================================================================
TERMINAL COLOR INTEGRATION *cp-terminal-colors*
ANSI colors automatically use your terminal's color palette through Neovim's
vim.g.terminal_color_* variables. This ensures compiler colors match your
colorscheme without manual configuration.
If your colorscheme doesn't set terminal colors, cp.nvim will warn you and
ANSI colors won't display properly - set them like so: >vim
let g:terminal_color_1 = '#ff6b6b'
...
==============================================================================
HIGHLIGHT CUSTOMIZATION *cp-highlight-custom*
You can customize any highlight group by linking to existing groups or
defining custom colors: >lua
-- Customize the color of "TLE" text in run panel:
vim.api.nvim_set_hl(0, 'CpTestTLE', { fg = '#ffa500', bold = true })
-- ... or the ANSI colors used to display stderr
vim.api.nvim_set_hl(0, 'CpAnsiRed', {
fg = vim.g.terminal_color_1 or '#ef4444'
})
<
Place customizations in your init.lua or after the colorscheme loads to
prevent them from being overridden: >lua
vim.api.nvim_create_autocmd('ColorScheme', {
callback = function()
-- Your cp.nvim highlight customizations here
vim.api.nvim_set_hl(0, 'CpTestAC', { link = 'String' })
end
})
<
==============================================================================
RUN PANEL KEYMAPS *cp-test-keys*
<c-n> Navigate to next test case (configurable via
run_panel.next_test_key)
<c-p> Navigate to previous test case (configurable via
run_panel.prev_test_key)
<c-t> Cycle through diff modes: none → git → vim (configurable
via run_panel.toggle_diff_key)
<c-q> Exit run panel/interactive terminal and restore layout
Diff Modes ~
Two diff backends are available:
vim Built-in vim diff (default, always available)
git Character-level git word-diff (requires git, more precise)
The git backend shows character-level changes with [-removed-] and {+added+}
markers for precise difference analysis.
Execution Details ~
Test cases are executed individually using the same compilation and
execution pipeline, but with isolated input/output for
precise failure analysis. All tests are automatically run when the
panel opens.
==============================================================================
FILE STRUCTURE *cp-files*
cp.nvim creates the following file structure upon problem setup: >
{problem_id}.{ext} " Source file (e.g. a.cc, b.py)
build/
{problem_id}.run " Compiled binary
io/
{problem_id}.n.cpin " nth test input
{problem_id}.n.cpout " nth program output
{problem_id}.expected " Expected output
<
==============================================================================
SNIPPETS *cp-snippets*
cp.nvim integrates with LuaSnip for automatic template expansion. Built-in
snippets include basic C++ and Python templates for each contest type.
Snippet trigger names must match the following format exactly: >
cp.nvim/{platform}.{language}
<
Where {platform} is the contest platform (atcoder, codeforces, cses) and
{language} is the programming language (cpp, python).
Examples: >
cp.nvim/atcoder.cpp
cp.nvim/codeforces.python
cp.nvim/cses.cpp
<
Custom snippets can be added via the `snippets` configuration field.
==============================================================================
HEALTH CHECK *cp-health*
Run |:checkhealth| cp to verify your setup.
vim:tw=78:ts=8:ft=help:norl: