Files
bbs-md/.planning/phases/02-vault-core-and-rendering/02-01-PLAN.md
T
2026-02-28 22:02:14 +01:00

7.2 KiB

phase, plan, type, wave, depends_on, files_modified, autonomous, requirements, must_haves
phase plan type wave depends_on files_modified autonomous requirements must_haves
02-vault-core-and-rendering 01 execute 1
Cargo.toml
src/vault.rs
src/highlighter.rs
true
REND-03
REND-10
NAV-06
NAV-07
truths artifacts key_links
pulldown-cmark, syntect, and syntect-tui compile without errors alongside existing ratatui 0.30
vault.rs can load a markdown file from a vault path and return structured success/missing/error states
highlighter.rs initializes syntect once and can highlight a code string into Vec<Line<'static>> with CGA 16-color palette
path provides contains
Cargo.toml pulldown-cmark, syntect, syntect-tui dependencies pulldown-cmark
path provides contains
src/vault.rs VaultDocument enum and load_document function VaultDocument
path provides contains
src/highlighter.rs syntect initialization, CGA color mapping, highlight_code function syntect_color_to_cga
from to via pattern
src/highlighter.rs syntect OnceLock<SyntaxSet> and OnceLock<ThemeSet> initialized once OnceLock.*SyntaxSet
from to via pattern
src/vault.rs std::fs read_to_string for markdown file loading read_to_string
Add Phase 2 dependencies (pulldown-cmark, syntect, syntect-tui) to Cargo.toml, create the vault file-loading module, and create the syntax highlighter module with CGA 16-color mapping.

Purpose: Establish the foundation libraries and I/O layer that the markdown renderer (Plan 02) and app integration (Plan 03) build upon. Output: Three files modified/created; cargo build succeeds with all new dependencies.

<execution_context> @/Users/ruohki/.claude/get-shit-done/workflows/execute-plan.md @/Users/ruohki/.claude/get-shit-done/templates/summary.md </execution_context>

@.planning/PROJECT.md @.planning/ROADMAP.md @.planning/STATE.md @.planning/phases/02-vault-core-and-rendering/02-RESEARCH.md @.planning/phases/02-vault-core-and-rendering/02-CONTEXT.md @src/config.rs @Cargo.toml Task 1: Add dependencies and create vault file-loading module Cargo.toml, src/vault.rs **Cargo.toml:** Add three new dependencies alongside the existing ones: ```toml pulldown-cmark = "0.13.1" syntect = { version = "5.3", default-features = false, features = ["default-fancy"] } syntect-tui = "3.0" ```

Note: default-features = false, features = ["default-fancy"] avoids the Oniguruma C library — pure Rust regex engine for clean SSH server builds.

src/vault.rs: Create a new module with:

  1. VaultDocument enum with three variants:

    • Loaded { path: PathBuf, content: String } — file read successfully
    • Missing { path: PathBuf } — file does not exist (io::ErrorKind::NotFound)
    • ReadError { path: PathBuf, reason: String } — other I/O error
  2. load_document(vault_path: &Path, relative: &str) -> VaultDocument:

    • Join vault_path with relative to get the full path
    • Use std::fs::read_to_string() with proper match on the Result
    • Map ErrorKind::NotFound to VaultDocument::Missing
    • Map other errors to VaultDocument::ReadError
    • Return VaultDocument::Loaded on success

The function takes vault_path (from Config) and a relative filename (e.g., "index.md").

Do NOT register the module in main.rs yet — Plan 03 handles wiring. cargo check passes with no errors (new deps resolve, vault.rs compiles). Run cargo check 2>&1 and confirm exit code 0. Cargo.toml has pulldown-cmark 0.13.1, syntect 5.3 with default-fancy, and syntect-tui 3.0. vault.rs exists with VaultDocument enum and load_document function. cargo check succeeds.

Task 2: Create syntax highlighter module with CGA color mapping src/highlighter.rs Create `src/highlighter.rs` with these components:
  1. Module-level OnceLock statics for one-time initialization:

    static SYNTAX_SET: OnceLock<SyntaxSet> = OnceLock::new();
    static THEME_SET: OnceLock<ThemeSet> = OnceLock::new();
    
  2. init_highlighter() — call once from main.rs before App::new():

    • SYNTAX_SET.get_or_init(SyntaxSet::load_defaults_newlines);
    • THEME_SET.get_or_init(ThemeSet::load_defaults);
  3. syntax_set() -> &'static SyntaxSet and theme_set() -> &'static ThemeSet accessor functions that call .get().expect(...).

  4. syntect_color_to_cga(c: syntect::highlighting::Color) -> ratatui::style::Color — RGB-to-CGA Euclidean distance mapper using the 16 CGA palette entries exactly as documented in the research (Pattern 8). The CGA palette entries:

    • Black(0,0,0), Red(170,0,0), Green(0,170,0), Yellow(170,170,0), Blue(0,0,170), Magenta(170,0,170), Cyan(0,170,170), Gray(170,170,170)
    • DarkGray(85,85,85), LightRed(255,85,85), LightGreen(85,255,85), LightYellow(255,255,85), LightBlue(85,85,255), LightMagenta(255,85,255), LightCyan(85,255,255), White(255,255,255)
  5. highlight_code(code: &str, lang: &str) -> Vec<Line<'static>> — the public API for code block highlighting:

    • Look up syntax by token first, then by name, fall back to plain text
    • Use HighlightLines::new(syntax, &theme_set().themes["base16-ocean.dark"])
    • For each line in code.lines(): call highlight_line(), map each (Style, &str) tuple to a Span::styled(text.to_string(), Style::default().fg(syntect_color_to_cga(style.foreground))), collect into Line::from(spans)
    • Return Vec<Line<'static>> (all owned strings, no lifetime leakage)

Do NOT register the module in main.rs yet — Plan 03 handles wiring. But do ensure the file compiles in isolation (no unresolved imports that depend on other new modules). cargo check passes. Verify highlighter.rs compiles by temporarily adding mod highlighter; to main.rs, running cargo check, then removing it. Or simply verify the file has no syntax errors by checking cargo check output. highlighter.rs exists with init_highlighter(), syntax_set(), theme_set(), syntect_color_to_cga(), and highlight_code() functions. All use OnceLock for one-time init. Output is Vec<Line<'static>> with CGA 16-color palette.

1. `cargo build` succeeds with all new dependencies 2. `src/vault.rs` contains `VaultDocument` enum with `Loaded`, `Missing`, `ReadError` variants 3. `src/vault.rs` contains `load_document()` function 4. `src/highlighter.rs` contains `init_highlighter()`, `highlight_code()`, `syntect_color_to_cga()` 5. No changes to existing Phase 1 files (app.rs, main.rs, config.rs, signals.rs, terminal.rs) other than Cargo.toml

<success_criteria>

  • cargo build compiles cleanly with pulldown-cmark 0.13.1, syntect 5.3, and syntect-tui 3.0
  • vault.rs provides file loading with structured error states (Loaded/Missing/ReadError)
  • highlighter.rs provides one-shot syntect initialization and CGA-mapped syntax highlighting
  • Both new modules produce 'static lifetime outputs (no borrowed data leaking) </success_criteria>
After completion, create `.planning/phases/02-vault-core-and-rendering/02-01-SUMMARY.md`