CP Runner
Zero-config competitive programming test runner for VS Code.
Run it (development)
npm install
npm run build # bundles src/extension.ts -> dist/extension.js via esbuild
Then in VS Code:
- Open this folder.
- Press
F5 (Run Extension). A new "Extension Development Host" window opens.
- In that window, open a folder shaped like:
problem/
main.cpp
tests/
1.in
1.out
2.in
2.out
- Open
main.cpp, press Ctrl+Enter. CP Runner compiles it, runs every test
in tests/, and shows verdicts in the sidebar (Activity Bar icon on the left).
Supported languages
C++ (g++), Python 3, Java, Rust, Go — detected from file extension. Each needs
its toolchain (g++, python3, javac/java, rustc, go) on PATH.
Keyboard shortcuts
| Shortcut |
Action |
| Ctrl+Enter |
Build & Run tests |
| Ctrl+Shift+B |
Build only |
| Ctrl+Shift+T |
Add test |
| Ctrl+Shift+R |
Stress test |
| Ctrl+Shift+G |
Generate random test |
How it works (file map)
src/
extension.ts activation, command + view registration
sidebar/
SidebarProvider.ts webview <-> runner glue, holds UI state
webview/index.html static shell (styles/script injected via URIs)
runner/
languageConfig.ts per-language build/run command definitions
discovery.ts finds problem root + tests/*.in|*.out pairs
build.ts compiles (or skips, for interpreted langs)
execute.ts spawns a run with timeout, captures stdout/time
testRunner.ts build -> run every test -> verdict (AC/WA/RE/TLE)
diff.ts line + first-char diff for the Wrong Answer view
stress.ts generator -> brute vs solution loop, auto-saves mismatch
generator.ts seeded random input generator
media/
main.js, style.css, icon.svg webview client (vanilla JS, no framework)
Why no React/Vite
The spec called for React + Vite, but the actual UI surface here is a handful
of rows, a couple of buttons, and two <pre> blocks. A framework buys nothing
at this size and adds a build step, a dependency tree, and slower reloads. Flat
HTML/CSS/JS keeps the whole webview under 250 lines and loads instantly. If the
UI grows a lot (multiple interactive panels, complex local state), swap
media/main.js for a small React bundle — SidebarProvider.ts already talks
to the webview purely through postMessage, so nothing else has to change.
Known simplifications (v0.1)
- Memory usage is not measured yet (
memoryKb is always 0) — needs an
/usr/bin/time -v wrapper on Linux/macOS; skip on Windows.
- Test rename/duplicate/delete aren't wired into the sidebar UI yet, only
add/select — the file-level operations (
fs.rename, copy, fs.unlink on
the .in/.out pair) are trivial to add to SidebarProvider.ts following
the addTest() pattern.
- Stress test generator is invoked with a bare seed as
argv[1]; adjust
stress.ts if your generator reads config differently.
- Whitespace-diff visualization toggle from the spec is not built —
diff.ts
already normalizes trailing whitespace for the AC/WA verdict; showing raw
whitespace as a toggle in the webview is a small addition to main.js.