1pub mod palette;
3
4pub use palette::Palette;
5
6use crate::Color;
7
8use std::fmt;
9use std::sync::Arc;
10
11#[derive(Debug, Clone, PartialEq)]
13pub enum Theme {
14 Light,
16 Dark,
18 Dracula,
20 Nord,
22 SolarizedLight,
24 SolarizedDark,
26 GruvboxLight,
28 GruvboxDark,
30 CatppuccinLatte,
32 CatppuccinFrappe,
34 CatppuccinMacchiato,
36 CatppuccinMocha,
38 TokyoNight,
40 TokyoNightStorm,
42 TokyoNightLight,
44 KanagawaWave,
46 KanagawaDragon,
48 KanagawaLotus,
50 Moonfly,
52 Nightfly,
54 Oxocarbon,
56 Ferra,
58 Custom(Arc<Custom>),
60}
61
62impl Theme {
63 pub const ALL: &'static [Self] = &[
65 Self::Light,
66 Self::Dark,
67 Self::Dracula,
68 Self::Nord,
69 Self::SolarizedLight,
70 Self::SolarizedDark,
71 Self::GruvboxLight,
72 Self::GruvboxDark,
73 Self::CatppuccinLatte,
74 Self::CatppuccinFrappe,
75 Self::CatppuccinMacchiato,
76 Self::CatppuccinMocha,
77 Self::TokyoNight,
78 Self::TokyoNightStorm,
79 Self::TokyoNightLight,
80 Self::KanagawaWave,
81 Self::KanagawaDragon,
82 Self::KanagawaLotus,
83 Self::Moonfly,
84 Self::Nightfly,
85 Self::Oxocarbon,
86 Self::Ferra,
87 ];
88
89 pub fn custom(name: String, palette: Palette) -> Self {
91 Self::custom_with_fn(name, palette, palette::Extended::generate)
92 }
93
94 pub fn custom_with_fn(
97 name: String,
98 palette: Palette,
99 generate: impl FnOnce(Palette) -> palette::Extended,
100 ) -> Self {
101 Self::Custom(Arc::new(Custom::with_fn(name, palette, generate)))
102 }
103
104 pub fn palette(&self) -> Palette {
106 match self {
107 Self::Light => Palette::LIGHT,
108 Self::Dark => Palette::DARK,
109 Self::Dracula => Palette::DRACULA,
110 Self::Nord => Palette::NORD,
111 Self::SolarizedLight => Palette::SOLARIZED_LIGHT,
112 Self::SolarizedDark => Palette::SOLARIZED_DARK,
113 Self::GruvboxLight => Palette::GRUVBOX_LIGHT,
114 Self::GruvboxDark => Palette::GRUVBOX_DARK,
115 Self::CatppuccinLatte => Palette::CATPPUCCIN_LATTE,
116 Self::CatppuccinFrappe => Palette::CATPPUCCIN_FRAPPE,
117 Self::CatppuccinMacchiato => Palette::CATPPUCCIN_MACCHIATO,
118 Self::CatppuccinMocha => Palette::CATPPUCCIN_MOCHA,
119 Self::TokyoNight => Palette::TOKYO_NIGHT,
120 Self::TokyoNightStorm => Palette::TOKYO_NIGHT_STORM,
121 Self::TokyoNightLight => Palette::TOKYO_NIGHT_LIGHT,
122 Self::KanagawaWave => Palette::KANAGAWA_WAVE,
123 Self::KanagawaDragon => Palette::KANAGAWA_DRAGON,
124 Self::KanagawaLotus => Palette::KANAGAWA_LOTUS,
125 Self::Moonfly => Palette::MOONFLY,
126 Self::Nightfly => Palette::NIGHTFLY,
127 Self::Oxocarbon => Palette::OXOCARBON,
128 Self::Ferra => Palette::FERRA,
129 Self::Custom(custom) => custom.palette,
130 }
131 }
132
133 pub fn extended_palette(&self) -> &palette::Extended {
135 match self {
136 Self::Light => &palette::EXTENDED_LIGHT,
137 Self::Dark => &palette::EXTENDED_DARK,
138 Self::Dracula => &palette::EXTENDED_DRACULA,
139 Self::Nord => &palette::EXTENDED_NORD,
140 Self::SolarizedLight => &palette::EXTENDED_SOLARIZED_LIGHT,
141 Self::SolarizedDark => &palette::EXTENDED_SOLARIZED_DARK,
142 Self::GruvboxLight => &palette::EXTENDED_GRUVBOX_LIGHT,
143 Self::GruvboxDark => &palette::EXTENDED_GRUVBOX_DARK,
144 Self::CatppuccinLatte => &palette::EXTENDED_CATPPUCCIN_LATTE,
145 Self::CatppuccinFrappe => &palette::EXTENDED_CATPPUCCIN_FRAPPE,
146 Self::CatppuccinMacchiato => {
147 &palette::EXTENDED_CATPPUCCIN_MACCHIATO
148 }
149 Self::CatppuccinMocha => &palette::EXTENDED_CATPPUCCIN_MOCHA,
150 Self::TokyoNight => &palette::EXTENDED_TOKYO_NIGHT,
151 Self::TokyoNightStorm => &palette::EXTENDED_TOKYO_NIGHT_STORM,
152 Self::TokyoNightLight => &palette::EXTENDED_TOKYO_NIGHT_LIGHT,
153 Self::KanagawaWave => &palette::EXTENDED_KANAGAWA_WAVE,
154 Self::KanagawaDragon => &palette::EXTENDED_KANAGAWA_DRAGON,
155 Self::KanagawaLotus => &palette::EXTENDED_KANAGAWA_LOTUS,
156 Self::Moonfly => &palette::EXTENDED_MOONFLY,
157 Self::Nightfly => &palette::EXTENDED_NIGHTFLY,
158 Self::Oxocarbon => &palette::EXTENDED_OXOCARBON,
159 Self::Ferra => &palette::EXTENDED_FERRA,
160 Self::Custom(custom) => &custom.extended,
161 }
162 }
163}
164
165impl Default for Theme {
166 fn default() -> Self {
167 #[cfg(feature = "auto-detect-theme")]
168 {
169 use std::sync::LazyLock;
170
171 static DEFAULT: LazyLock<Theme> = LazyLock::new(|| {
172 match dark_light::detect()
173 .unwrap_or(dark_light::Mode::Unspecified)
174 {
175 dark_light::Mode::Dark => Theme::Dark,
176 dark_light::Mode::Light | dark_light::Mode::Unspecified => {
177 Theme::Light
178 }
179 }
180 });
181
182 DEFAULT.clone()
183 }
184
185 #[cfg(not(feature = "auto-detect-theme"))]
186 Theme::Light
187 }
188}
189
190impl fmt::Display for Theme {
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 match self {
193 Self::Light => write!(f, "Light"),
194 Self::Dark => write!(f, "Dark"),
195 Self::Dracula => write!(f, "Dracula"),
196 Self::Nord => write!(f, "Nord"),
197 Self::SolarizedLight => write!(f, "Solarized Light"),
198 Self::SolarizedDark => write!(f, "Solarized Dark"),
199 Self::GruvboxLight => write!(f, "Gruvbox Light"),
200 Self::GruvboxDark => write!(f, "Gruvbox Dark"),
201 Self::CatppuccinLatte => write!(f, "Catppuccin Latte"),
202 Self::CatppuccinFrappe => write!(f, "Catppuccin Frappé"),
203 Self::CatppuccinMacchiato => write!(f, "Catppuccin Macchiato"),
204 Self::CatppuccinMocha => write!(f, "Catppuccin Mocha"),
205 Self::TokyoNight => write!(f, "Tokyo Night"),
206 Self::TokyoNightStorm => write!(f, "Tokyo Night Storm"),
207 Self::TokyoNightLight => write!(f, "Tokyo Night Light"),
208 Self::KanagawaWave => write!(f, "Kanagawa Wave"),
209 Self::KanagawaDragon => write!(f, "Kanagawa Dragon"),
210 Self::KanagawaLotus => write!(f, "Kanagawa Lotus"),
211 Self::Moonfly => write!(f, "Moonfly"),
212 Self::Nightfly => write!(f, "Nightfly"),
213 Self::Oxocarbon => write!(f, "Oxocarbon"),
214 Self::Ferra => write!(f, "Ferra"),
215 Self::Custom(custom) => custom.fmt(f),
216 }
217 }
218}
219
220#[derive(Debug, Clone, PartialEq)]
222pub struct Custom {
223 name: String,
224 palette: Palette,
225 extended: palette::Extended,
226}
227
228impl Custom {
229 pub fn new(name: String, palette: Palette) -> Self {
231 Self::with_fn(name, palette, palette::Extended::generate)
232 }
233
234 pub fn with_fn(
237 name: String,
238 palette: Palette,
239 generate: impl FnOnce(Palette) -> palette::Extended,
240 ) -> Self {
241 Self {
242 name,
243 palette,
244 extended: generate(palette),
245 }
246 }
247}
248
249impl fmt::Display for Custom {
250 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
251 write!(f, "{}", self.name)
252 }
253}
254
255#[derive(Debug, Clone, Copy, PartialEq)]
257pub struct Style {
258 pub background_color: Color,
260
261 pub text_color: Color,
263}
264
265pub trait Base {
267 fn base(&self) -> Style;
269}
270
271impl Base for Theme {
272 fn base(&self) -> Style {
273 default(self)
274 }
275}
276
277pub fn default(theme: &Theme) -> Style {
279 let palette = theme.extended_palette();
280
281 Style {
282 background_color: palette.background.base.color,
283 text_color: palette.background.base.text,
284 }
285}