Files

12 KiB
Raw Permalink Blame History

viexp Roadmap — Rust + English in 20-hour sprints

Method: Josh Kaufman, "The First 20 Hours" — rapid skill acquisition. The project is split into isolated 20-hour sprints (~45 min/day for a month each). Every sprint: one Rust sub-skill, one working app increment, one English artifact. The goal of each sprint is to cross the frustration barrier and ship something that runs — not perfect code.

Kaufman's rules, adapted

Kaufman principle How this roadmap applies it
Deconstruct the skill The table below: each sprint = one sub-skill + one app increment
Learn just enough to self-correct Per-sprint "Rust focus — the vital 20%": the minimum theory to read your own compiler errors. Every error goes to the ErrorJournal with a self-correction cue
Remove barriers to practice Sprint 0 sets up the whole environment: toolchain, linters, fast feedback (bacon), Gitea board, CI. Never debug your setup during practice time
Fast feedback loops cargo check/bacon on save, unit tests per session, immediate AI code review of each session's diff (commit → review → fix)
Quantity over quality Many small commits, many small drills. Working ugly code beats beautiful unfinished code. No over-engineering before v0.1

Skill deconstruction

Rust sub-skills (learned in order): cargo & project layout → types & control flow → ownership/borrowing → structs, enums, pattern matching → Option/Result & ? → modules & crates → traits & generics → iterators → Path/fs & error handling (thiserror/anyhow) → serde/TOML → lifetimes → trait objects & dynamic dispatch → threads & channels → async/await & tokio → process spawning → caching & performance.

App increments (each demoable): vls CLI → 3-pane TUI → navigation & file ops → config & openers → text previews → image previews → document previews → media & async → script plugins → power features → performance → release.

English track: every commit message, every issue, all docs — English only. One written artifact per sprint. Daily DevLog (3–5 sentences). See workflows/english-workflow.

Session rhythm (45 min, every day)

  1. 5 min — read yesterday's DevLog + ErrorJournal; git pull, bacon starts.
  2. 30 min — today's drill or feature slice (one drill = one commit).
  3. 10 min — get the diff reviewed, fix what the reviewer flags, write the DevLog entry.

Frustration rules: stuck >20 min on one error → ask for a review instead of grinding; never end a session with broken code (revert to green); a slow day is a reading day (Rust Book chapter in English) — log it, no guilt.

Sprints

Legend: 🎯 milestone. Each sprint gets a docs/sprints/sprint-NN-*.md note (Sprint template) and a Gitea milestone with issues created from its Definition of Done.


Sprint 0 — Setup & deconstruction (≈6 h, short)

  • App deliverable: empty viexp cargo project that compiles, cargo test runs one trivial test, CI (Gitea Actions) is green, bacon + clippy + rustfmt wired, Gitea board ready.
  • Rust focus: toolchain mental model — what cargo, rustc, crates.io, Cargo.toml are; read your first compiler error on purpose (break a program, fix it).
  • English: README "Status" section + the vault (this roadmap counts).
  • DoD: cargo bacon shows check+test on save; first commit pushed; Sprint-1 issues exist.

Sprint 1 — Rust core via vls (20 h)

  • App deliverable: viexp ls subcommand — a better ls: colored names by type, human-readable sizes, --sort name|size|mtime, --hidden, --long; ≥10 unit tests.
  • Rust focus (vital 20%): variables & types, functions, if/match, loops, Vec/String vs &str, structs & enums, Option/Result + ?, modules, #[cfg(test)]. Rust Book ch. 1–9 (skim 7/8), rustlings intro→enums.
  • English: README usage section; article "Why build a file manager in Rust" (draft).
  • DoD: vls ~/ output beats ls for your eyes; clippy clean; tests green.

Sprint 2 — First TUI (20 h) — the borrow-checker sprint

  • App deliverable: three-pane Miller layout (parent / current / placeholder preview), j/k/gg/G cursor movement, :q quits, resize-safe redraw, no flicker.
  • Rust focus: ownership & borrowing in anger (the state struct owns everything), references vs clones, lifetimes as they appear in ratatui calls, the event-loop pattern (poll event → mutate state → redraw). Rust Book ch. 4, 10.3 (skim), ratatui official docs.
  • English: keymap reference table in docs (precise imperative phrasing).
  • DoD: navigate a 10k-file directory smoothly; panic-free for 15 min of use.

Sprint 3 — Navigation & file ops (20 h) 🎯 M1: personal daily driver

  • App deliverable: enter/leave directories, hidden toggle, sort cycling, Space/V selection, yy/dd/pp copy/cut/paste, delete → first-class trash (freedescompliant) with undo, :mkdir :touch :rename, status bar (path, size, free space — not per-frame statvfs; 1 Hz poll).
  • Rust focus: Path/PathBuf, fs::read_dir/metadata, real error handling (thiserror for lib-style internals, anyhow at main), iterators (map/filter/sort_by chains), Display impls.
  • English: article "Week one of dogfooding my own file manager".
  • DoD: use viexp instead of ranger for real work for 3 days; log every pain point as an issue.

Sprint 4 — Config & openers (20 h)

  • App deliverable: viexp.toml (defaults, theme colors, sort) + modules.toml registry v0 (ADR-003): mime/glob → opener, per-module enabled, user rules prepend/append; opener engine (infer + xdg-mime → rule table → xdg-open fallback), r "open with" menu, :open_with.
  • Rust focus: serde derive on enums/structs, Default + merge semantics, HashMap/ BTreeMap, first trait design (Opener), builder-ish config loading with helpful errors.
  • English: configuration guide draft (reference-style writing).
  • DoD: any file opens with your preferred app from config alone; broken TOML produces a friendly error, not a panic.

Sprint 5 — Text previews & bulk rename (20 h)

  • App deliverable: preview pane v1 — syntax-highlighted text (syntect) with line numbers and scrolling, directory preview, file metadata panel, zip/tar listing, :bulkrename via $EDITOR (ranger's killer feature), n/N plain search, : command history.
  • Rust focus: lifetimes in real signatures, trait objects (Box<dyn Previewer> registry), advanced iterators, caching keyed by (path, mtime).
  • English: article "How a TUI paints text" (explaining rendering → strongest writing practice).
  • DoD: preview parity with ranger for text/code/archive files.

Sprint 6 — Image previews (20 h) 🎯 M2a

  • App deliverable: image module through the registry; kitty graphics adapter first (owner's terminal), chafa/halfblocks floor; thumbnail disk cache + LRU; runtime disable/replace via modules.toml proven on images.
  • Rust focus: the image crate, decode/resize pipeline, #[cfg(feature)] modules, pixel data, spawning helper processes safely.
  • English: article "How terminals display images" (kitty protocol, sixel, ueberzug++ — your best future blog post; research notes already hold the material).
  • DoD: PNG/JPEG/WebP/GIF preview instantly in kitty; enabled=false kills it in one line.

Sprint 7 — Document previews (20 h) 🎯 M2b: full ranger replacement

  • App deliverable: PDF (pdfium-render, Apache-2.0), EPUB (hand-rolled zip+XML — GPL trap avoided), Markdown (comrak/termimad), DJVU (djvu-rs + ddjvu fallback config). All as registry modules, all runtime-disableable.
  • Rust focus: binary data & byte streams, feature-gated crates, error taxonomy design, more trait objects; reading crate docs as a skill.
  • English: module documentation pages (PDF/EPUB/DJVU) in user-guide style.
  • DoD: your entire document library previews; ranger uninstalled.

Sprint 8 — Media & async (20 h) 🎯 M2c

  • App deliverable: video thumbnail (spawn ffmpeg -ss … -vframes 1), audio metadata + cover art (ffprobe JSON), background preview pipeline: std threads + mpsc now, generation-counter cancellation, large-directory pagination; adopt tokio for the pipeline by sprint end (ADR-005).
  • Rust focus: std::thread, mpsc, Arc/Mutex, then async/await, tokio::spawn, select!, cancellation patterns. Rust Book ch. 16 + async book chapters (English only!).
  • English: article "Async Rust for a skeptic" — explain threads-vs-tokio in your own words.
  • DoD: 4K-video directory scrolls at full speed; huge directory never blocks input.

Sprint 9 — Script plugin protocol (20 h) 🎯 M3a: extensible

  • App deliverable: freeze the external plugin contract (ADR-002 phase 2): previewer argv (path, w, h, x, y) + env context + FIFO write-back + cleaner hook; documented exit codes & SIGPIPE; opener scripts; plugins/ dir discovery; two reference plugins (bash: torrent info; python: git repo summary).
  • Rust focus: process spawning & pipes, timeouts, safe command construction (no shell injection), protocol design & semver, integration tests with fixture scripts.
  • English: plugin author guide — the sprint's main artifact; write it as if for strangers.
  • DoD: a script written only from the guide (no source peeking) works.

Sprint 10 — Power features (20 h) 🎯 M3b: feature parity with your ranger config

  • App deliverable: tabs, bookmarks + marks, fuzzy finder (nucleo) with interruptible search (broot lesson), :commands set (:find :delete :copy…), push key-simulation, shell integration --choosefile/--choosedir/--selectfile, cd-on-exit wrapper script, session restore.
  • Rust focus: state machines (modes), Rc-free architecture review, macro_rules! for keymap tables, API refactoring under tests.
  • English: article "Vim-style UX patterns in file managers".
  • DoD: your shell rc sources the viexp wrapper; fuzzy find feels instant.

Sprint 11 — Performance & robustness (20 h)

  • App deliverable: notify-based live directory updates, virtual scrolling, startup <50 ms, one-week dogfood with zero panics, tracing logs to file, panic hook restores the terminal, criterion benchmarks committed, crash-fix buffer.
  • Rust focus: profiling (cargo flamegraph, perf), benchmarking (criterion), reading someone else's code (yazi's) for patterns, hardening.
  • English: article "Profiling a TUI app: making viexp start in 40 ms".
  • DoD: benchmark numbers in README; a week of daily use logged.

Sprint 12 — Release & docs (20 h) 🎯 M4: v0.1.0 public

  • App deliverable: v0.1.0 — cargo-dist release builds, AUR PKGBUILD, Gitea release + changelog, user guide (mdBook in-repo), plugin examples gallery, install docs.
  • Rust focus: release engineering, MSRV policy, feature matrix testing, rustdoc comments on the public plugin API.
  • English: the user guide is the largest English artifact of the project; polish it hard.
  • DoD: a stranger installs from AUR and writes a plugin using only the docs.

Backlog (post-1.0, priority order)

Embedded Lua plugins (mlua, ADR-002 phase 3) · sixel/iTerm2/ueberzug++ adapters · DDS-style inter-instance pub/sub · NNN_FIFO-style hover event stream · themes gallery · zoxide jump · archive mount/browsing depth.

Milestones

Milestone After sprint Meaning
M1 3 daily driver for basic navigation/file ops
M2a–c 6–8 full ranger replacement (images, docs, media)
M3a–b 9–10 extensible by scripts, feature parity
M4 12 v0.1.0 released publicly

At 45 min/day this is roughly a 12–13 month journey to v0.1.0 — the point is a working product and durable skills, in that order, every single sprint.

Cadence & safety nets

  • Sprint notes live in docs/sprints/; each sprint's DoD becomes Gitea issues (milestone per sprint) — see workflows/gitea-workflow.
  • If a sprint overruns by >30%, cut scope from the bottom of its DoD — never silently skip tests.
  • One "buffer week" is allowed between sprints; more than one means the sprint was too big — re-decompose in the retro.