feat(theme): add theme randomizer and save-to-disk

Theme::random() conjures a fresh procedural vestment — a coherent HSV
palette (dark tinted surface, one bright accent, legible ink), a random
sigil, and a generated arcane name. Bound to Ctrl+Alt+P and `/theme random`.

Theme::save() persists the vestment you're wearing to themes/<slug>.toml
(via `/theme save [name]`), so a roll you like can be re-donned later with
`/theme <name>`. Theme now derives Serialize and slugify() sanitizes the
filename. Help text and the /theme usage line advertise both verbs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
leetcrypt
2026-06-02 17:39:37 -07:00
parent 0417ef89cc
commit 00c1f1c3c9
3 changed files with 237 additions and 4 deletions
+9 -1
View File
@@ -146,7 +146,7 @@ fn help_lines(theme: &Theme) -> Vec<Line<'static>> {
// List whatever vestments are actually installed, so new themes show up here
// automatically (church · neon · crypt · blush · matrix · wraith · …).
let theme_help = format!(
"change vestments live: {}",
"vestments: {} · random · save [name]",
Theme::available().join(" · ")
);
vec![
@@ -209,6 +209,14 @@ fn help_lines(theme: &Theme) -> Vec<Line<'static>> {
"Ctrl-R (when closed)",
"reconnect to the house after a drop / AFK",
),
kv(
"Ctrl+Alt+P · /theme random",
"conjure a random vestment (new palette + sigil)",
),
kv(
"/theme save [name]",
"keep the vestment you're wearing for reuse",
),
kv("Ctrl-C · Ctrl-Q", "quit hack-house"),
Line::from(""),
head("ROSTER GLYPHS"),