supercode_harness/tui/theme.rs
1//! P5-4 (§3.1 `capabilities.tui.theme`, D8 "themes"): the SEMANTIC theme
2//! choice — which of the built-in named roles (accent, dim, error, …) a
3//! renderer should map to actual terminal colors. Deliberately carries no
4//! `ratatui::style::Color` (or any other terminal-library type) so this
5//! stays part of the terminal-free view-model core; `crates/cli`'s
6//! render layer owns the actual RGB/ANSI mapping.
7
8/// A built-in theme name. `Dark` is the default (matches
9/// `Config::tui_theme`'s `"dark"` default).
10#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
11pub enum Theme {
12 /// Default — matches most terminals' dark-background convention.
13 #[default]
14 Dark,
15 /// Light-background terminal.
16 Light,
17}
18
19impl Theme {
20 /// Parse `capabilities.tui.theme`'s string value. Unknown values fall
21 /// back to [`Theme::Dark`] rather than erroring — a themed cosmetic
22 /// setting is never worth refusing to start the TUI over.
23 pub fn parse(s: &str) -> Self {
24 match s.to_ascii_lowercase().as_str() {
25 "light" => Theme::Light,
26 _ => Theme::Dark,
27 }
28 }
29
30 /// The toggle [`crate::tui::Action::ToggleTheme`] cycles to.
31 pub fn toggled(self) -> Self {
32 match self {
33 Theme::Dark => Theme::Light,
34 Theme::Light => Theme::Dark,
35 }
36 }
37
38 /// A short, human-readable name for the status line.
39 pub fn label(self) -> &'static str {
40 match self {
41 Theme::Dark => "dark",
42 Theme::Light => "light",
43 }
44 }
45}
46
47#[cfg(test)]
48mod tests {
49 use super::*;
50
51 #[test]
52 fn parse_known_and_unknown() {
53 assert_eq!(Theme::parse("light"), Theme::Light);
54 assert_eq!(Theme::parse("LIGHT"), Theme::Light);
55 assert_eq!(Theme::parse("dark"), Theme::Dark);
56 assert_eq!(Theme::parse("bogus"), Theme::Dark);
57 assert_eq!(Theme::parse(""), Theme::Dark);
58 }
59
60 #[test]
61 fn toggle_round_trips() {
62 assert_eq!(Theme::Dark.toggled(), Theme::Light);
63 assert_eq!(Theme::Light.toggled(), Theme::Dark);
64 assert_eq!(Theme::Dark.toggled().toggled(), Theme::Dark);
65 }
66
67 #[test]
68 fn default_is_dark() {
69 assert_eq!(Theme::default(), Theme::Dark);
70 }
71}