caixa_theme/
blackmatter.rs1use crate::palette::{Nord, Rgb};
8use crate::style::Semantic;
9
10#[derive(Debug, Clone, Copy)]
11pub struct Theme {
12 pub name: &'static str,
13 resolver: fn(Semantic) -> Rgb,
14}
15
16impl Theme {
17 #[must_use]
18 pub fn blackmatter_dark() -> Self {
19 Self {
20 name: "blackmatter-dark",
21 resolver: blackmatter_dark_color,
22 }
23 }
24
25 #[must_use]
26 pub fn blackmatter_light() -> Self {
27 Self {
28 name: "blackmatter-light",
29 resolver: blackmatter_light_color,
30 }
31 }
32
33 #[must_use]
34 pub fn color(&self, s: Semantic) -> Rgb {
35 (self.resolver)(s)
36 }
37
38 #[must_use]
39 pub fn ansi(&self, s: Semantic) -> String {
40 self.color(s).fg_ansi()
41 }
42
43 #[must_use]
44 pub fn paint(&self, s: Semantic, text: &str) -> String {
45 format!("{}{}{}", self.ansi(s), text, crate::palette::ANSI_RESET)
46 }
47}
48
49impl Default for Theme {
50 fn default() -> Self {
51 Self::blackmatter_dark()
52 }
53}
54
55fn blackmatter_dark_color(s: Semantic) -> Rgb {
56 match s {
57 Semantic::Keyword => Nord::NORD9,
58 Semantic::Symbol => Nord::NORD4,
59 Semantic::KeywordArg => Nord::NORD8,
60 Semantic::String => Nord::NORD14,
61 Semantic::Number => Nord::NORD15,
62 Semantic::Literal => Nord::NORD13,
63 Semantic::Comment => Nord::NORD3,
64 Semantic::Accent => Nord::NORD8,
65 Semantic::Muted => Nord::NORD3,
66 Semantic::Error => Nord::NORD11,
67 Semantic::Warning => Nord::NORD12,
68 Semantic::Info => Nord::NORD8,
69 Semantic::Hint => Nord::NORD13,
70 Semantic::Added => Nord::NORD14,
71 Semantic::Removed => Nord::NORD11,
72 Semantic::Unchanged => Nord::NORD4,
73 }
74}
75
76fn blackmatter_light_color(s: Semantic) -> Rgb {
77 match s {
79 Semantic::Keyword => Nord::NORD10,
80 Semantic::Symbol => Nord::NORD0,
81 Semantic::KeywordArg => Nord::NORD10,
82 Semantic::String => Nord::NORD14,
83 Semantic::Number => Nord::NORD15,
84 Semantic::Literal => Nord::NORD12,
85 Semantic::Comment => Nord::NORD2,
86 Semantic::Accent => Nord::NORD10,
87 Semantic::Muted => Nord::NORD2,
88 Semantic::Error => Nord::NORD11,
89 Semantic::Warning => Nord::NORD12,
90 Semantic::Info => Nord::NORD10,
91 Semantic::Hint => Nord::NORD13,
92 Semantic::Added => Nord::NORD14,
93 Semantic::Removed => Nord::NORD11,
94 Semantic::Unchanged => Nord::NORD0,
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn default_is_dark() {
104 let t = Theme::default();
105 assert_eq!(t.name, "blackmatter-dark");
106 }
107
108 #[test]
109 fn error_maps_to_red() {
110 let t = Theme::blackmatter_dark();
111 assert_eq!(t.color(Semantic::Error), Nord::NORD11);
112 }
113
114 #[test]
115 fn paint_wraps_with_reset() {
116 let t = Theme::blackmatter_dark();
117 let out = t.paint(Semantic::Error, "boom");
118 assert!(out.starts_with("\x1b["));
119 assert!(out.ends_with(crate::palette::ANSI_RESET));
120 assert!(out.contains("boom"));
121 }
122}