Files
lumbridge-code/tools/theme-gen/README.md
T
Metal AgentandClaude Opus 5 401760d670 Generate the theme catalog from real themes instead of a hand table
The derivation landed in decision 0018 with the catalog and the terminal ANSI
palette still fixed tables written by hand. tools/theme-gen reads the
TextMate themes under assets/themes/ and emits the catalog and the reference
vectors, so the anchors a palette is derived from are the ones the theme
actually ships rather than the ones somebody transcribed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SPYebLiN2w4TqnHUYGdECq
2026-09-01 12:51:25 -07:00

61 lines
2.8 KiB
Markdown

# theme-gen
Turns the theme files vendored in `assets/themes/` into
`crates/lumbridge-theme/src/generated/catalog.rs` and
`assets/themes/NOTICE-THEMES.md`.
```bash
cargo run -p theme-gen # rewrite both files
cargo run -p theme-gen -- --check # fail if either is out of date
```
Dev-only. Nothing in the workspace depends on it at build time, and `--check` is
the hook a future CI step would use.
## Why it is a binary and not a `build.rs`
Two reasons, in order of weight.
The colours a user sees should be reviewable as text in a pull request. If an
upstream theme changes a hex digit, that should arrive as a diff someone reads,
not as a silently different build. Everything this tool produces is checked in
for exactly that reason, and `--check` is what keeps the checked-in copy honest.
And a build that reads `assets/themes/` makes the asset tree a build input.
Trimming assets in a packaging step would then break compilation rather than
breaking a theme picker, which is the wrong failure.
## What it decides, and what it only measures
The tool makes no aesthetic choices. It applies rules and records what they
produced:
- **Anchors.** `editor.background`, `editor.foreground`, the comment token's
foreground, and the git-decoration colours, by the rules in `src/extract.rs`.
- **Terminal palette.** The theme's `terminal.ansi*` keys where it has them, a
syntax token that stands for the same role where it does not, and a documented
hue derived from the theme's own foreground where it has neither.
- **Contrast gate.** A theme whose body text measures below 4.5:1 against the
surface Lumbridge derives for it is held back, and the measurement is written
into the generated file's header. Three themes currently fail.
- **Distinctness.** Two escape codes that would paint the same colour, and two
role colours that would make decision 0012's provenance shades identical, are
forced apart — and every such substitution is written down twice: as a comment
above the theme, and in a machine-readable constant the tests read back.
Licence exclusion happens **before** this tool, at the vendoring step, so a GPL
theme is never in the tree at all. See `assets/themes/SOURCE.md`.
## `reference/`
`reference/emit-reference-vectors.mjs` regenerates
`crates/lumbridge-theme/src/generated/reference_vectors.rs` by running Buzz's
original TypeScript under Node over the same vendored theme files. It needs the
Buzz checkout, which lives outside this repository and is pinned in
`docs/RESEARCH_SNAPSHOTS.md`, so it is not a step CI can run — which is why its
output is checked in and the test that reads it runs everywhere.
Run it only when the derivation itself changes. Decision 0018 explains at some
length why these vectors must come from running the original and never from
re-deriving them.