1use serde::{Deserialize, Serialize};
7
8use crate::palette::{Luminance, Palette};
9
10#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, Serialize, Deserialize)]
14pub enum Scheme {
15 #[default]
16 Catppuccin,
17 Gruvbox,
18 RosePine,
19 Everforest,
20 Ayu,
21 TokyoNight,
22}
23
24impl Scheme {
25 pub const ALL: [Scheme; 6] = [
26 Scheme::Catppuccin,
27 Scheme::Gruvbox,
28 Scheme::RosePine,
29 Scheme::Everforest,
30 Scheme::Ayu,
31 Scheme::TokyoNight,
32 ];
33
34 pub fn display_name(self) -> &'static str {
35 match self {
36 Scheme::Catppuccin => "Catppuccin",
37 Scheme::Gruvbox => "Gruvbox",
38 Scheme::RosePine => "RosΓ© Pine",
39 Scheme::Everforest => "Everforest",
40 Scheme::Ayu => "Ayu",
41 Scheme::TokyoNight => "Tokyo Night",
42 }
43 }
44
45 pub fn palette(self, luminance: Luminance) -> Palette {
47 match (self, luminance.is_dark()) {
48 (Scheme::Catppuccin, true) => Palette::catppuccin_mocha(),
49 (Scheme::Catppuccin, false) => Palette::catppuccin_latte(),
50 (Scheme::Gruvbox, true) => Palette::gruvbox_dark(),
51 (Scheme::Gruvbox, false) => Palette::gruvbox_light(),
52 (Scheme::RosePine, true) => Palette::rose_pine(),
53 (Scheme::RosePine, false) => Palette::rose_pine_dawn(),
54 (Scheme::Everforest, true) => Palette::everforest_dark(),
55 (Scheme::Everforest, false) => Palette::everforest_light(),
56 (Scheme::Ayu, true) => Palette::ayu_dark(),
57 (Scheme::Ayu, false) => Palette::ayu_light(),
58 (Scheme::TokyoNight, true) => Palette::tokyo_night_dark(),
59 (Scheme::TokyoNight, false) => Palette::tokyo_night_light(),
60 }
61 }
62}
63
64#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, Serialize, Deserialize)]
68pub enum Mode {
69 Light,
70 #[default]
71 Dark,
72 System,
73}
74
75impl Mode {
76 pub const ALL: [Mode; 3] = [Mode::Light, Mode::Dark, Mode::System];
77
78 pub fn display_name(self) -> &'static str {
79 match self {
80 Mode::Light => "Light",
81 Mode::Dark => "Dark",
82 Mode::System => "System",
83 }
84 }
85
86 pub fn glyph(self) -> &'static str {
87 match self {
88 Mode::Light => "β",
89 Mode::Dark => "π",
90 Mode::System => "π»",
91 }
92 }
93
94 pub fn is_dark(self, system_dark: Option<bool>) -> bool {
97 match self {
98 Mode::Light => false,
99 Mode::Dark => true,
100 Mode::System => system_dark.unwrap_or(true),
101 }
102 }
103}
104
105#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, Serialize, Deserialize)]
109pub enum FontChoice {
110 #[default]
111 Basic,
112 Formal,
113 Monospace,
114 Sketchy,
115}
116
117impl FontChoice {
118 pub const ALL: [FontChoice; 4] = [
119 FontChoice::Basic,
120 FontChoice::Formal,
121 FontChoice::Monospace,
122 FontChoice::Sketchy,
123 ];
124
125 pub fn display_name(self) -> &'static str {
126 match self {
127 FontChoice::Basic => "Basic",
128 FontChoice::Formal => "Formal",
129 FontChoice::Monospace => "Monospace",
130 FontChoice::Sketchy => "Sketchy",
131 }
132 }
133
134 pub fn family_name(self) -> &'static str {
137 match self {
138 FontChoice::Basic => "Roboto",
139 FontChoice::Formal => "Forum",
140 FontChoice::Monospace => "Iosevka",
141 FontChoice::Sketchy => "Excalifont",
142 }
143 }
144
145 pub fn bytes(self) -> &'static [u8] {
148 match self {
149 FontChoice::Basic => crate::font::ROBOTO,
150 FontChoice::Formal => crate::font::FORUM,
151 FontChoice::Monospace => crate::font::IOSEVKA,
152 FontChoice::Sketchy => crate::font::EXCALIFONT,
153 }
154 }
155}
156
157#[cfg(test)]
158mod tests {
159 use super::*;
160
161 #[test]
162 fn every_scheme_has_a_dark_and_a_light_variant() {
163 for scheme in Scheme::ALL {
164 assert!(scheme.palette(Luminance::Dark).is_dark(), "{scheme:?} dark");
165 assert!(
166 !scheme.palette(Luminance::Light).is_dark(),
167 "{scheme:?} light"
168 );
169 }
170 }
171
172 #[test]
173 fn mode_resolves_dark_following_the_os_for_system() {
174 assert!(!Mode::Light.is_dark(Some(true)));
175 assert!(Mode::Dark.is_dark(Some(false)));
176 assert!(Mode::System.is_dark(Some(true)));
178 assert!(!Mode::System.is_dark(Some(false)));
179 assert!(Mode::System.is_dark(None));
180 }
181}