Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 13 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
Code Practice (Neovim)
======================

A local, Neovim-native practice plugin for browsing exercises, solving them in
buffer, and running tests from the editor.
A Neovim plugin for browsing coding exercises, solving them, and running tests
— all without leaving the editor.

Features
--------
Expand Down Expand Up @@ -30,7 +30,8 @@ Using [lazy.nvim](https://github.com/folke/lazy.nvim):
}
```

Then populate the exercise database. The simplest way is to import a JSON file:
Then populate the exercise database. The simplest way is to import a JSON file
(see [`test/example_exercises.json`](test/example_exercises.json) for the expected schema):

```vim
:CPImport /path/to/exercises.json
Expand Down Expand Up @@ -103,9 +104,7 @@ Browser Keymaps
| `m` | Toggle filter: medium difficulty|
| `h` | Toggle filter: hard difficulty |
| `a` | Clear all filters |
| `p` | Toggle filter: Python |
| `r` | Toggle filter: Rust |
| `t` | Toggle filter: Theory |
| per-engine key | Toggle filter by engine (defaults: `p` Python, `r` Rust, `t` Theory) |
| `gg` | Go to top of list |
| `G` | Go to bottom of list |
| `q` | Close browser |
Expand Down Expand Up @@ -139,14 +138,14 @@ Tools
### Exercise Generator

Generate exercises from a syllabus using Hugging Face models. The generator is
fully language-agnostic: the LLM produces a self-contained test harness alongside
each exercise, so adding a new language is just a run command — no Python glue code needed.
engine-agnostic: the LLM produces a self-contained test harness alongside
each exercise, so adding a new engine is just a run command — no Python glue code needed.

Requires [uv](https://docs.astral.sh/uv/) and a HF token (set via `HF_TOKEN` env var, or `huggingface-cli login`).

Configuration lives in two TOML files under `tools/`:
- **`languages.toml`** — defines supported languages (run commands, prompt rules,
required fields). Add a new language here; no Python changes needed.
- **`engines.toml`** — defines supported engines (run commands, prompt rules,
required fields). Add a new engine here; no Python changes needed.
- **`syllabus.toml`** — defines what to generate (topics, counts, difficulties).

```bash
Expand All @@ -159,11 +158,11 @@ uv run tools/generate_exercises.py tools/syllabus.toml --model Qwen/Qwen3-Coder-
# Dry run (print JSON, don't insert)
uv run tools/generate_exercises.py tools/syllabus.toml --dry-run

# Use a custom languages config
uv run tools/generate_exercises.py tools/syllabus.toml --languages my_languages.toml
# Use a custom engines config
uv run tools/generate_exercises.py tools/syllabus.toml --engines my_engines.toml
```

Or from Neovim: `:CPGenerate` (prompts for topic, count, difficulty, and language).
Or from Neovim: `:CPGenerate` (prompts for topic, count, difficulty, and engine).

Data
----
Expand All @@ -179,7 +178,7 @@ Roadmap
- [ ] Context-aware LLM hint based on current buffer code
- [ ] Live timer with opt-out config
- [ ] Git theory questions
- [ ] Haskell runner
- [ ] Haskell engine

Development
-----------
Expand Down
6 changes: 1 addition & 5 deletions dev/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,20 +33,16 @@ require("code-practice").setup({
height = 0.8,
border = "rounded",
},
languages = {
engines = {
python = {
enabled = true,
cmd = "python3",
ext = "py",
},
rust = {
enabled = false,
cmd = "rustc",
ext = "rs",
},
theory = {
enabled = true,
ext = "md",
},
},
keymaps = {
Expand Down
Loading