{"id":47948259,"url":"https://github.com/davidefiocco/code-practice","last_synced_at":"2026-04-04T08:52:53.257Z","repository":{"id":340113859,"uuid":"1164573010","full_name":"davidefiocco/code-practice","owner":"davidefiocco","description":"A neovim plugin to practice code quizzes","archived":false,"fork":false,"pushed_at":"2026-03-09T10:53:25.000Z","size":185,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-04T08:52:50.998Z","etag":null,"topics":["code-practice","neovim"],"latest_commit_sha":null,"homepage":"","language":"Lua","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/davidefiocco.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-23T08:38:21.000Z","updated_at":"2026-03-06T22:38:52.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/davidefiocco/code-practice","commit_stats":null,"previous_names":["davidefiocco/code-practice"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/davidefiocco/code-practice","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidefiocco%2Fcode-practice","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidefiocco%2Fcode-practice/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidefiocco%2Fcode-practice/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidefiocco%2Fcode-practice/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/davidefiocco","download_url":"https://codeload.github.com/davidefiocco/code-practice/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/davidefiocco%2Fcode-practice/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31393781,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-04T04:26:24.776Z","status":"ssl_error","status_checked_at":"2026-04-04T04:23:34.147Z","response_time":60,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["code-practice","neovim"],"created_at":"2026-04-04T08:52:51.808Z","updated_at":"2026-04-04T08:52:53.245Z","avatar_url":"https://github.com/davidefiocco.png","language":"Lua","funding_links":[],"categories":[],"sub_categories":[],"readme":"Code Practice (Neovim)\n======================\n\nA Neovim plugin for browsing coding exercises, solving them (potentially getting some help from AI 🤖), and running tests — all without leaving the editor.\n\nFeatures\n--------\n- Browser UI with preview for exercises\n- Deterministic navigation: next, skip, previous\n- Extensible engine registry: interpreted and compiled runners\n- Theory questions with answer checking\n- Results window and solution viewer\n- LLM-powered exercise generation (see Tools below)\n- LLM-powered context-aware hints (opt-in, via Hugging Face Inference API)\n\nInstallation\n------------\nUsing [lazy.nvim](https://github.com/folke/lazy.nvim):\n\n```lua\n{\n  \"davidefiocco/code-practice\",\n  dependencies = {\n    \"MunifTanjim/nui.nvim\",\n    \"kkharji/sqlite.lua\",\n  },\n  config = function()\n    require(\"code-practice\").setup()\n  end,\n}\n```\n\nThen populate the exercise database. The simplest way is to import a JSON file\n(see [`test/example_exercises.json`](test/example_exercises.json) for the expected schema):\n\n```vim\n:CP import /path/to/exercises.json\n```\n\nOr set `exercises_json` in your config to auto-import on first run:\n\n```lua\nrequire(\"code-practice\").setup({\n  storage = {\n    exercises_json = \"/path/to/exercises.json\",\n  },\n})\n```\n\nYou can also generate exercises with an LLM (requires [uv](https://docs.astral.sh/uv/) and a [Hugging Face token](https://huggingface.co/settings/tokens)):\n\n```bash\ncd ~/.local/share/nvim/lazy/code-practice\nexport HF_TOKEN=your_token\nuv run tools/generate_exercises.py tools/syllabus.toml\n```\n\nOr from Neovim: `:CP generate`.\n\nRequirements\n------------\n- Neovim 0.10+\n- MunifTanjim/nui.nvim\n- kkharji/sqlite.lua\n- Engine executables for each enabled engine (run `:checkhealth code-practice`)\n\nQuick Start\n-----------\n1. Open browser: `:CP`\n2. Navigate with `j`/`k`, open with `Enter`\n3. Write your solution in the buffer\n4. Run tests: `Ctrl-t`\n5. Move on: `Ctrl-n`\n\nCommands\n--------\nEverything goes through a single `:CP` command with subcommands.\nTab completion is supported: type `:CP \u003cTab\u003e` to explore.\n\n| Command               | Description                          |\n|-----------------------|--------------------------------------|\n| `:CP` or `:CP open`  | Open exercise browser                |\n| `:CP close`          | Close the browser                    |\n| `:CP refresh`        | Refresh the browser list             |\n| `:CP stats`          | Show practice statistics             |\n| `:CP help`           | Show the in-editor quick guide       |\n| `:CP import \u003cpath\u003e`  | Import exercises from a JSON file    |\n| `:CP! import \u003cpath\u003e` | Replace all exercises from JSON      |\n| `:CP generate`       | Generate exercises via LLM           |\n\nExercise-level actions (run tests, next, skip, hints, solution, etc.) are\navailable via buffer-local keymaps only (see below).\n\nBrowser Keymaps\n---------------\n| Key       | Action                          |\n|-----------|---------------------------------|\n| `j` / `k` | Move selection down / up       |\n| `Enter`   | Open selected exercise          |\n| `o`       | Open selected exercise          |\n| `e`       | Toggle filter: easy difficulty  |\n| `m`       | Toggle filter: medium difficulty|\n| `h`       | Toggle filter: hard difficulty  |\n| `a`       | Clear all filters               |\n| per-engine key | Toggle filter by engine (defaults: `p` Python, `r` Rust, `t` Theory) |\n| `gg`      | Go to top of list               |\n| `G`       | Go to bottom of list            |\n| `q`       | Close browser                   |\n| `Esc`     | Close browser                   |\n| `?`       | Show help guide                 |\n\nExercise Buffer Keymaps\n-----------------------\nActive in normal mode inside exercise buffers. All use Ctrl shortcuts for\nsingle-chord access (configurable via `keymaps.exercise`):\n\n| Key       | Action                          |\n|-----------|---------------------------------|\n| `Ctrl-t`  | Run tests                       |\n| `Ctrl-n`  | Next exercise                   |\n| `Ctrl-p`  | Previous exercise               |\n| `Ctrl-k`  | Skip exercise                   |\n| `Ctrl-i`  | Show hints                      |\n| `Ctrl-l`  | View solution (split)           |\n| `Ctrl-d`  | Show description                |\n| `Ctrl-b`  | Open browser                    |\n\nTools\n-----\n### Exercise Generator\n\nGenerate exercises from a syllabus using Hugging Face models. The generator is\nengine-agnostic: the LLM produces a self-contained test harness alongside\neach exercise, so adding a new engine is just a run command — no Python glue code needed.\n\nRequires [uv](https://docs.astral.sh/uv/) and a HF token (set via `HF_TOKEN` env var, or `huggingface-cli login`).\n\nConfiguration lives in two TOML files under `tools/`:\n- **`engines.toml`** — defines supported engines (run commands, prompt rules,\n  required fields). Add a new engine here; no Python changes needed.\n- **`syllabus.toml`** — defines what to generate (topics, counts, difficulties).\n\n```bash\n# Generate from syllabus (default model: Qwen/Qwen3-Coder-Next)\nuv run tools/generate_exercises.py tools/syllabus.toml\n\n# Custom model\nuv run tools/generate_exercises.py tools/syllabus.toml --model Qwen/Qwen3-Coder-30B-A3B-Instruct\n\n# Dry run (print JSON, don't insert)\nuv run tools/generate_exercises.py tools/syllabus.toml --dry-run\n\n# Use a custom engines config\nuv run tools/generate_exercises.py tools/syllabus.toml --engines my_engines.toml\n```\n\nOr from Neovim: `:CP generate` (prompts for topic, count, difficulty, and engine).\n\n### AI Hints\n\nWhen enabled, `Ctrl-i` generates a context-aware hint using a Hugging Face model\ninstead of showing static hints. The hint is based on your current buffer and the\nreference solution.\n\nRequires `curl` and a HF token (`HF_TOKEN` env var).\n\n```lua\nrequire(\"code-practice\").setup({\n  ai_hints = {\n    enabled = true,\n    model = \"Qwen/Qwen3-Coder-Next\",  -- default\n  },\n})\n```\n\nData\n----\nExercises are stored in an SQLite database at `stdpath(\"data\")/code-practice/exercises.db`.\nImport exercises from a JSON file with `:CP import \u003cpath\u003e`, or use `:CP! import \u003cpath\u003e` to\nreplace existing data. The database path is configurable via `storage.db_path`.\n\nThe database schema is defined in [`schema.sql`](schema.sql) at the repository root and\nshared by the Lua plugin, the test seeder, and the exercise generator.\n\nRoadmap\n-------\n- [ ] Random exercise (`:CP random`)\n- [ ] Search widget in browser\n- [ ] Bug-finding exercise type\n- [ ] Live timer with opt-out config\n- [ ] Git theory questions\n- [ ] Haskell engine\n\nDevelopment\n-----------\nA minimal Neovim config for local development lives in `dev/init.lua`:\n\n```bash\nnvim -u dev/init.lua\n```\n\n### Testing\n\nThe test suite runs headless Neovim inside Docker:\n\n```bash\ndocker build -t code-practice-test .\ndocker run --rm code-practice-test\n```\n\nCI runs both linting (stylua + selene) and the Docker test suite on every push\nand pull request. See `.github/workflows/test.yml`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidefiocco%2Fcode-practice","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdavidefiocco%2Fcode-practice","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdavidefiocco%2Fcode-practice/lists"}