docs: bootstrap vault, roadmap and research
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
---
|
||||
type: decision
|
||||
adr: 001
|
||||
status: accepted
|
||||
date: 2026-10-17
|
||||
supersedes:
|
||||
tags: [adr, ratatui, tui]
|
||||
---
|
||||
|
||||
# ADR-001: ratatui + crossterm as the TUI foundation
|
||||
|
||||
## Context
|
||||
viexp needs a terminal UI with a three-pane Miller layout, an event loop, and later image
|
||||
graphics. The Rust TUI ecosystem has one de-facto standard and several niche options.
|
||||
|
||||
## Options considered
|
||||
| Option | Pros | Cons |
|
||||
|--------|------|------|
|
||||
| **ratatui + crossterm** | De-facto standard (yazi, felix, broot); 0.30 modular facade; ratatui-image companion; huge docs/community | Immediate-mode model to learn; subcrate churn in 2026 |
|
||||
| cursive | widget-toolkit feel | slower cadence, different paradigm |
|
||||
| tui-realm | retained mode on ratatui | extra complexity for one maintainer |
|
||||
| tui-rs | — | dead upstream |
|
||||
| hand-rolled on crossterm | total control | reinvents widgets; hunter died with this approach |
|
||||
|
||||
## Decision
|
||||
Use **ratatui 0.30 (facade) with the crossterm backend**. Pin minor versions in Cargo.toml;
|
||||
adopt the ratatui-org `ratatui-image` crate when previews arrive (Sprint 6).
|
||||
|
||||
## Consequences
|
||||
- Positive: best-documented path; skills transfer to yazi/helix-adjacent tooling; image widget exists.
|
||||
- Negative: immediate-mode rendering must be learned early (owned by Sprint 2); 0.30 subcrate
|
||||
split may cause dependency churn.
|
||||
- Mitigations: pin versions; single render function per pane; UI state isolated in one struct.
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
type: decision
|
||||
adr: 002
|
||||
status: accepted
|
||||
date: 2026-10-17
|
||||
supersedes:
|
||||
tags: [adr, plugins, architecture]
|
||||
---
|
||||
|
||||
# ADR-002: three-phase extension architecture (TOML → scripts → Lua)
|
||||
|
||||
## Context
|
||||
viexp must let Linux users disable, replace and add file-type behaviors easily. Research
|
||||
([[research/plugin-architecture]]) shows: declarative rules carry configuration, external
|
||||
process contracts carry ~90% of real-world extension, and embedded interpreters are the most
|
||||
expensive layer to stabilize (yazi is still "beta" partly because of it). WASM (zellij) costs
|
||||
host complexity that a single-maintainer learning project cannot afford.
|
||||
|
||||
## Options considered
|
||||
| Option | Pros | Cons |
|
||||
|--------|------|------|
|
||||
| Phased: TOML rules → script contract → Lua (mlua) | each phase shippable; users' language of choice; no unsafe early | three layers to document eventually |
|
||||
| Lua from day 1 | yazi-grade power early | API design + FFI before first working product; high frustration risk |
|
||||
| WASM components (wasmtime/extism) | best sandboxing | WIT churn, users must compile components; zellij-scale effort |
|
||||
| External-only | simplest | no stateful in-process previews/fetchers ever |
|
||||
|
||||
## Decision (confirmed with the project owner, 2026-10-17)
|
||||
1. **v0.1 — declarative registry**: `modules.toml` maps mime/glob → previewer/opener; per-module
|
||||
`enabled` switch; user rules merge via `prepend_*`/`append_*` (yazi semantics). All built-in
|
||||
modules dispatch through the same tables.
|
||||
2. **v0.2 — external process contract (frozen, documented)**: previewer argv = `(path, width,
|
||||
height, x, y)`; env context (mime, selection file, session dir); write-back via FIFO/socket
|
||||
(nnn-style opcodes); `cleaner` hook; documented exit codes + SIGPIPE semantics.
|
||||
Reference plugins in bash and Python ship in-repo.
|
||||
3. **v1.0+ — embedded Lua** via **mlua with vendored Lua**, registered through the same tables;
|
||||
only for what scripts cannot do (stateful/in-process previews). Re-evaluate Luau if sandbox
|
||||
isolation becomes a requirement. **WASM is explicitly rejected for v1.x.**
|
||||
|
||||
## Consequences
|
||||
- Positive: shippable increments; extension by Linux-familiar means; Lua postponed until the
|
||||
host API is stable enough to expose.
|
||||
- Negative: three layers of documentation eventually; write-back protocol must be designed
|
||||
carefully once and frozen.
|
||||
- Mitigations: one dispatch model for all layers (yazi lesson); contract docs written as part
|
||||
of the v0.2 sprint DoD, not after.
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
type: decision
|
||||
adr: 003
|
||||
status: accepted
|
||||
date: 2026-10-17
|
||||
supersedes:
|
||||
tags: [adr, modules, config]
|
||||
---
|
||||
|
||||
# ADR-003: file-type modules are registry entries, disableable at runtime
|
||||
|
||||
## Context
|
||||
Requirement: images, video, audio, PDF, DJVU, EPUB and Markdown previews work out of the box,
|
||||
but a user can disable or replace any of them without recompiling. Cargo features alone fail
|
||||
this: feature unification breaks packagers, and removing a default feature is a breaking
|
||||
change ([[research/plugin-architecture]]).
|
||||
|
||||
## Options considered
|
||||
| Option | Pros | Cons |
|
||||
|--------|------|------|
|
||||
| Runtime registry + per-module `enabled` flag (+ optional cargo features for binary size) | one-line disable; replaceable by script rule; packager-safe | slightly larger default binary |
|
||||
| Cargo features only | smallest binaries | recompile to disable; unification traps; breaking-change semantics |
|
||||
| Everything external scripts (ranger scope.sh model) | max flexibility | out-of-box experience degrades; 700-line bash nobody dares edit |
|
||||
|
||||
## Decision
|
||||
Every file-type capability is a **module** registered in a TOML registry:
|
||||
`name`, `match` (mime/glob), `previewer` (built-in id or external command), `opener`,
|
||||
`enabled` (default true). Precedence: user rules → built-in rules, with `prepend_/append_`
|
||||
merge. Built-in implementations live behind additive cargo features (default-on: `image`,
|
||||
`pdf`, `media`, …) purely to trim binaries; a feature-disabled module degrades to a TOML rule
|
||||
pointing at an external tool (e.g. `pdftotext`) instead of disappearing.
|
||||
|
||||
## Consequences
|
||||
- Positive: `enabled = false` in one line; third-party replacement without recompile; matches
|
||||
ADR-002 phase 1 exactly.
|
||||
- Negative: two config concepts (registry + features) need clear documentation.
|
||||
- Mitigations: features documented as "binary size only, not functionality"; docs page
|
||||
"Disabling and replacing modules" is part of the v0.1 docs DoD.
|
||||
@@ -0,0 +1,43 @@
|
||||
---
|
||||
type: decision
|
||||
adr: 004
|
||||
status: accepted
|
||||
date: 2026-10-17
|
||||
supersedes:
|
||||
tags: [adr, preview, kitty, sixel]
|
||||
---
|
||||
|
||||
# ADR-004: image preview protocol chain (kitty first)
|
||||
|
||||
## Context
|
||||
Ranger's biggest UX liability is image preview depending on unmaintained X11-only ueberzug.
|
||||
Research ([[research/rust-preview-stack]]): terminals support one of several incompatible
|
||||
graphics protocols; no single one covers everything. The owner's daily terminal is **kitty
|
||||
without a multiplexer**, but viexp targets all Linux users.
|
||||
|
||||
## Options considered
|
||||
| Option | Pros | Cons |
|
||||
|--------|------|------|
|
||||
| Multi-protocol chain behind one trait, runtime detection (yazi model) | works everywhere; upgrade path | most implementation work |
|
||||
| kitty-only | minimal work for owner's setup | useless for everyone else; vifm/nnn trap |
|
||||
| Always chafa/halfblocks | works everywhere incl. ssh | ugly; not a differentiator |
|
||||
|
||||
## Decision
|
||||
Implement a `GraphicsAdapter` trait with a **priority chain, first match wins**:
|
||||
1. **kitty graphics** (unicode-placeholder mode) — kitty ≥0.28, Ghostty — implemented first
|
||||
2. **iTerm2 inline** images
|
||||
3. **sixel** (via ratatui-image/quantette)
|
||||
4. **ueberzug++ subprocess** (X11 + wlroots Wayland)
|
||||
5. **chafa/halfblocks** — universal floor
|
||||
6. plain text (name, size, mime)
|
||||
|
||||
Detection: `$TERM`/`$TERM_PROGRAM`/`$XDG_SESSION_TYPE` env + terminal capability queries;
|
||||
shortcut via `ratatui-image` `Picker`, with ueberzug++/chafa as our tiers 4–5.
|
||||
Thumbnails: decode once at preview size → disk cache → in-memory LRU → neighbor preloading.
|
||||
|
||||
## Consequences
|
||||
- Positive: owner gets tier-1 quality from Sprint 6; everyone else degrades gracefully;
|
||||
no dead X11 dependency.
|
||||
- Negative: five adapters is real work; tmux/alacritty edge cases documented, not solved.
|
||||
- Mitigations: chain built incrementally (kitty in Sprint 6, sixel/ueberzug++ in the backlog);
|
||||
adapter chosen once per session, cached.
|
||||
@@ -0,0 +1,38 @@
|
||||
---
|
||||
type: decision
|
||||
adr: 005
|
||||
status: accepted
|
||||
date: 2026-10-17
|
||||
supersedes:
|
||||
tags: [adr, async, tokio, threads]
|
||||
---
|
||||
|
||||
# ADR-005: adopt async gradually — sync core, then threads, then tokio
|
||||
|
||||
## Context
|
||||
Ranger's fatal flaw is a synchronous loop that stats every file inline ([[research/ranger-deep-dive]]).
|
||||
yazi proves tokio solves it but is a lot of machinery to learn while also learning Rust.
|
||||
lf (Go goroutines) shows threads alone already keep a UI responsive.
|
||||
|
||||
## Options considered
|
||||
| Option | Pros | Cons |
|
||||
|--------|------|------|
|
||||
| Gradual: sync → std threads + channels → tokio | learnable steps; working product at every stage | one refactor of the preview pipeline in Sprint 8 |
|
||||
| tokio from day 1 | final architecture sooner | async lifetimes + borrow checker + TUI at once = frustration barrier |
|
||||
| threads-only forever | simpler mental model | ecosystem (notify bridges, timeouts, process spawning) is tokio-first |
|
||||
|
||||
## Decision
|
||||
- **Sprints 1–5**: synchronous core. The TUI loop owns all state; directory loading and file
|
||||
ops are fast enough synchronously for a first product.
|
||||
- **Sprints 6–7**: previews move to `std::thread` + `std::sync::mpsc` — UI stays responsive,
|
||||
ownership lessons are explicit.
|
||||
- **Sprint 8**: adopt **tokio** for the full preview/media pipeline (yazi architecture:
|
||||
runtime workers marshal results to the single-threaded UI actor via a channel). Introduce
|
||||
cancellation via a generation-counter ("ticket") pattern before adopting tokio `abort`.
|
||||
|
||||
## Consequences
|
||||
- Positive: each concurrency model is learned in isolation; no big-bang async rewrite of the UI.
|
||||
- Negative: preview pipeline is written twice (thread → task) — accepted as a deliberate
|
||||
learning repetition (Kaufman: quantity of practice beats premature perfection).
|
||||
- Mitigations: keep the preview pipeline behind a small interface (`Previewer` trait, ADR-002)
|
||||
so the swap is local, not global.
|
||||
Reference in New Issue
Block a user