1use anstyle::RgbColor;
2use catppuccin::PALETTE;
3use hashbrown::HashMap;
4use once_cell::sync::Lazy;
5
6use crate::types::{ThemeDefinition, ThemePalette, ThemeSuite};
7
8#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
9enum CatppuccinFlavorKind {
10 Latte,
11 Frappe,
12 Macchiato,
13 Mocha,
14}
15
16impl CatppuccinFlavorKind {
17 const fn id(self) -> &'static str {
18 match self {
19 Self::Latte => "catppuccin-latte",
20 Self::Frappe => "catppuccin-frappe",
21 Self::Macchiato => "catppuccin-macchiato",
22 Self::Mocha => "catppuccin-mocha",
23 }
24 }
25
26 const fn label(self) -> &'static str {
27 match self {
28 Self::Latte => "Catppuccin Latte",
29 Self::Frappe => "Catppuccin Frappé",
30 Self::Macchiato => "Catppuccin Macchiato",
31 Self::Mocha => "Catppuccin Mocha",
32 }
33 }
34
35 fn flavor(self) -> catppuccin::Flavor {
36 match self {
37 Self::Latte => PALETTE.latte,
38 Self::Frappe => PALETTE.frappe,
39 Self::Macchiato => PALETTE.macchiato,
40 Self::Mocha => PALETTE.mocha,
41 }
42 }
43}
44
45static CATPPUCCIN_FLAVORS: &[CatppuccinFlavorKind] = &[
46 CatppuccinFlavorKind::Latte,
47 CatppuccinFlavorKind::Frappe,
48 CatppuccinFlavorKind::Macchiato,
49 CatppuccinFlavorKind::Mocha,
50];
51
52static REGISTRY: Lazy<HashMap<&'static str, ThemeDefinition>> = Lazy::new(|| {
53 let mut map = HashMap::new();
54 map.insert(
55 "ciapre-dark",
56 ThemeDefinition {
57 id: "ciapre-dark",
58 label: "Ciapre Dark",
59 palette: ThemePalette {
60 primary_accent: RgbColor(0xBF, 0xB3, 0x8F),
61 background: RgbColor(0x26, 0x26, 0x26),
62 foreground: RgbColor(0xBF, 0xB3, 0x8F),
63 secondary_accent: RgbColor(0xD9, 0x9A, 0x4E),
64 alert: RgbColor(0xFF, 0x8A, 0x8A),
65 logo_accent: RgbColor(0xD9, 0x9A, 0x4E),
66 },
67 },
68 );
69 map.insert(
70 "ciapre-blue",
71 ThemeDefinition {
72 id: "ciapre-blue",
73 label: "Ciapre Blue",
74 palette: ThemePalette {
75 primary_accent: RgbColor(0xBF, 0xB3, 0x8F),
76 background: RgbColor(0x17, 0x1C, 0x26),
77 foreground: RgbColor(0xBF, 0xB3, 0x8F),
78 secondary_accent: RgbColor(0xBF, 0xB3, 0x8F),
79 alert: RgbColor(0xFF, 0x8A, 0x8A),
80 logo_accent: RgbColor(0xD9, 0x9A, 0x4E),
81 },
82 },
83 );
84 map.insert(
85 "ciapre",
86 ThemeDefinition {
87 id: "ciapre",
88 label: "Ciapre",
89 palette: ThemePalette {
90 primary_accent: RgbColor(0xAE, 0xA4, 0x7F),
91 background: RgbColor(0x18, 0x18, 0x18),
92 foreground: RgbColor(0xAE, 0xA4, 0x7F),
93 secondary_accent: RgbColor(0xCC, 0x8A, 0x3E),
94 alert: RgbColor(0xAC, 0x38, 0x35),
95 logo_accent: RgbColor(0xCC, 0x8A, 0x3E),
96 },
97 },
98 );
99 map.insert(
100 "solarized-dark",
101 ThemeDefinition {
102 id: "solarized-dark",
103 label: "Solarized Dark",
104 palette: ThemePalette {
105 primary_accent: RgbColor(0x83, 0x94, 0x96),
106 background: RgbColor(0x00, 0x2B, 0x36),
107 foreground: RgbColor(0x83, 0x94, 0x96),
108 secondary_accent: RgbColor(0x26, 0x8B, 0xD2),
109 alert: RgbColor(0xDC, 0x32, 0x2F),
110 logo_accent: RgbColor(0xB5, 0x89, 0x00),
111 },
112 },
113 );
114 map.insert(
115 "solarized-light",
116 ThemeDefinition {
117 id: "solarized-light",
118 label: "Solarized Light",
119 palette: ThemePalette {
120 primary_accent: RgbColor(0x58, 0x6E, 0x75),
121 background: RgbColor(0xFD, 0xF6, 0xE3),
122 foreground: RgbColor(0x58, 0x6E, 0x75),
123 secondary_accent: RgbColor(0x26, 0x8B, 0xD2),
124 alert: RgbColor(0xDC, 0x32, 0x2F),
125 logo_accent: RgbColor(0xB5, 0x89, 0x00),
126 },
127 },
128 );
129 map.insert(
130 "solarized-dark-hc",
131 ThemeDefinition {
132 id: "solarized-dark-hc",
133 label: "Solarized Dark Higher Contrast",
134 palette: ThemePalette {
135 primary_accent: RgbColor(0x83, 0x94, 0x96),
136 background: RgbColor(0x00, 0x28, 0x31),
137 foreground: RgbColor(0xE9, 0xE3, 0xCC),
138 secondary_accent: RgbColor(0x20, 0x76, 0xC7),
139 alert: RgbColor(0xD1, 0x1C, 0x24),
140 logo_accent: RgbColor(0xA5, 0x77, 0x06),
141 },
142 },
143 );
144 map.insert(
145 "gruvbox-dark",
146 ThemeDefinition {
147 id: "gruvbox-dark",
148 label: "Gruvbox Dark",
149 palette: ThemePalette {
150 primary_accent: RgbColor(0xA8, 0x99, 0x84),
151 background: RgbColor(0x28, 0x28, 0x28),
152 foreground: RgbColor(0xA8, 0x99, 0x84),
153 secondary_accent: RgbColor(0x45, 0x85, 0x88),
154 alert: RgbColor(0xCC, 0x24, 0x1D),
155 logo_accent: RgbColor(0xD7, 0x99, 0x21),
156 },
157 },
158 );
159 map.insert(
160 "gruvbox-dark-hard",
161 ThemeDefinition {
162 id: "gruvbox-dark-hard",
163 label: "Gruvbox Dark Hard",
164 palette: ThemePalette {
165 primary_accent: RgbColor(0xA8, 0x99, 0x84),
166 background: RgbColor(0x1D, 0x20, 0x21),
167 foreground: RgbColor(0xA8, 0x99, 0x84),
168 secondary_accent: RgbColor(0x45, 0x85, 0x88),
169 alert: RgbColor(0xCC, 0x24, 0x1D),
170 logo_accent: RgbColor(0xD7, 0x99, 0x21),
171 },
172 },
173 );
174 map.insert(
175 "gruvbox-light",
176 ThemeDefinition {
177 id: "gruvbox-light",
178 label: "Gruvbox Light",
179 palette: ThemePalette {
180 primary_accent: RgbColor(0x7C, 0x6F, 0x64),
181 background: RgbColor(0xFB, 0xF4, 0xE8),
182 foreground: RgbColor(0x7C, 0x6F, 0x64),
183 secondary_accent: RgbColor(0x45, 0x85, 0x88),
184 alert: RgbColor(0x9D, 0x00, 0x06),
185 logo_accent: RgbColor(0xB5, 0x76, 0x14),
186 },
187 },
188 );
189 map.insert(
190 "gruvbox-light-hard",
191 ThemeDefinition {
192 id: "gruvbox-light-hard",
193 label: "Gruvbox Light Hard",
194 palette: ThemePalette {
195 primary_accent: RgbColor(0x50, 0x49, 0x45),
196 background: RgbColor(0xF9, 0xF5, 0xD7),
197 foreground: RgbColor(0x50, 0x49, 0x45),
198 secondary_accent: RgbColor(0x45, 0x85, 0x88),
199 alert: RgbColor(0x9D, 0x00, 0x06),
200 logo_accent: RgbColor(0xB5, 0x76, 0x14),
201 },
202 },
203 );
204 map.insert(
205 "gruvbox-material",
206 ThemeDefinition {
207 id: "gruvbox-material",
208 label: "Gruvbox Material",
209 palette: ThemePalette {
210 primary_accent: RgbColor(0xD4, 0xBE, 0x98),
211 background: RgbColor(0x28, 0x2E, 0x33),
212 foreground: RgbColor(0xD4, 0xBE, 0x98),
213 secondary_accent: RgbColor(0x89, 0xB4, 0x82),
214 alert: RgbColor(0xEA, 0x69, 0x62),
215 logo_accent: RgbColor(0xE7, 0xA7, 0x2F),
216 },
217 },
218 );
219 map.insert(
220 "gruvbox-material-dark",
221 ThemeDefinition {
222 id: "gruvbox-material-dark",
223 label: "Gruvbox Material Dark",
224 palette: ThemePalette {
225 primary_accent: RgbColor(0xD4, 0xBE, 0x98),
226 background: RgbColor(0x28, 0x2E, 0x33),
227 foreground: RgbColor(0xD4, 0xBE, 0x98),
228 secondary_accent: RgbColor(0x89, 0xB4, 0x82),
229 alert: RgbColor(0xEA, 0x69, 0x62),
230 logo_accent: RgbColor(0xE7, 0xA7, 0x2F),
231 },
232 },
233 );
234 map.insert(
235 "gruvbox-material-light",
236 ThemeDefinition {
237 id: "gruvbox-material-light",
238 label: "Gruvbox Material Light",
239 palette: ThemePalette {
240 primary_accent: RgbColor(0x65, 0x49, 0x31),
241 background: RgbColor(0xFB, 0xF1, 0xC7),
242 foreground: RgbColor(0x65, 0x49, 0x31),
243 secondary_accent: RgbColor(0x4C, 0x7A, 0x5D),
244 alert: RgbColor(0xC1, 0x4A, 0x4A),
245 logo_accent: RgbColor(0xB4, 0x71, 0x09),
246 },
247 },
248 );
249 map.insert(
250 "ayu",
251 ThemeDefinition {
252 id: "ayu",
253 label: "Ayu Dark",
254 palette: ThemePalette {
255 primary_accent: RgbColor(0xE6, 0xE1, 0xCF),
256 background: RgbColor(0x0F, 0x14, 0x19),
257 foreground: RgbColor(0xE6, 0xE1, 0xCF),
258 secondary_accent: RgbColor(0x39, 0xBA, 0xE6),
259 alert: RgbColor(0xFF, 0x33, 0x33),
260 logo_accent: RgbColor(0xE6, 0xB4, 0x50),
261 },
262 },
263 );
264 map.insert(
265 "ayu-mirage",
266 ThemeDefinition {
267 id: "ayu-mirage",
268 label: "Ayu Mirage",
269 palette: ThemePalette {
270 primary_accent: RgbColor(0xCB, 0xCC, 0xCC),
271 background: RgbColor(0x1F, 0x24, 0x2D),
272 foreground: RgbColor(0xCB, 0xCC, 0xCC),
273 secondary_accent: RgbColor(0x5C, 0xC5, 0xFF),
274 alert: RgbColor(0xFF, 0x66, 0x66),
275 logo_accent: RgbColor(0xFF, 0xCC, 0x66),
276 },
277 },
278 );
279 map.insert(
280 "dracula",
281 ThemeDefinition {
282 id: "dracula",
283 label: "Dracula",
284 palette: ThemePalette {
285 primary_accent: RgbColor(0xF8, 0xF8, 0xF2),
286 background: RgbColor(0x28, 0x2A, 0x36),
287 foreground: RgbColor(0xF8, 0xF8, 0xF2),
288 secondary_accent: RgbColor(0x8B, 0xE9, 0xFD),
289 alert: RgbColor(0xFF, 0x55, 0x55),
290 logo_accent: RgbColor(0xFF, 0xB8, 0x6C),
291 },
292 },
293 );
294 map.insert(
295 "github-dark",
296 ThemeDefinition {
297 id: "github-dark",
298 label: "GitHub Dark",
299 palette: ThemePalette {
300 primary_accent: RgbColor(0xC9, 0xD1, 0xD9),
301 background: RgbColor(0x0D, 0x11, 0x17),
302 foreground: RgbColor(0xC9, 0xD1, 0xD9),
303 secondary_accent: RgbColor(0x58, 0xA6, 0xFF),
304 alert: RgbColor(0xF8, 0x51, 0x49),
305 logo_accent: RgbColor(0xD2, 0x99, 0x22),
306 },
307 },
308 );
309 map.insert(
310 "github",
311 ThemeDefinition {
312 id: "github",
313 label: "GitHub Light",
314 palette: ThemePalette {
315 primary_accent: RgbColor(0x24, 0x29, 0x2E),
316 background: RgbColor(0xFF, 0xFF, 0xFF),
317 foreground: RgbColor(0x24, 0x29, 0x2E),
318 secondary_accent: RgbColor(0x03, 0x66, 0xD6),
319 alert: RgbColor(0xD7, 0x3A, 0x49),
320 logo_accent: RgbColor(0xB0, 0x88, 0x00),
321 },
322 },
323 );
324 map.insert(
325 "atom-one-dark",
326 ThemeDefinition {
327 id: "atom-one-dark",
328 label: "Atom One Dark",
329 palette: ThemePalette {
330 primary_accent: RgbColor(0xAB, 0xB2, 0xBF),
331 background: RgbColor(0x28, 0x2C, 0x34),
332 foreground: RgbColor(0xAB, 0xB2, 0xBF),
333 secondary_accent: RgbColor(0x61, 0xAF, 0xEF),
334 alert: RgbColor(0xE0, 0x6C, 0x75),
335 logo_accent: RgbColor(0xE5, 0xC0, 0x7B),
336 },
337 },
338 );
339 map.insert(
340 "atom-one-light",
341 ThemeDefinition {
342 id: "atom-one-light",
343 label: "Atom One Light",
344 palette: ThemePalette {
345 primary_accent: RgbColor(0x38, 0x3A, 0x42),
346 background: RgbColor(0xFA, 0xFA, 0xFA),
347 foreground: RgbColor(0x38, 0x3A, 0x42),
348 secondary_accent: RgbColor(0x40, 0x73, 0xC9),
349 alert: RgbColor(0xE4, 0x56, 0x49),
350 logo_accent: RgbColor(0x98, 0x62, 0x00),
351 },
352 },
353 );
354 map.insert(
355 "tomorrow",
356 ThemeDefinition {
357 id: "tomorrow",
358 label: "Tomorrow",
359 palette: ThemePalette {
360 primary_accent: RgbColor(0x4D, 0x4D, 0x4C),
361 background: RgbColor(0xFF, 0xFF, 0xFF),
362 foreground: RgbColor(0x4D, 0x4D, 0x4C),
363 secondary_accent: RgbColor(0x42, 0x7B, 0xA4),
364 alert: RgbColor(0xC8, 0x28, 0x29),
365 logo_accent: RgbColor(0xAE, 0x7B, 0x03),
366 },
367 },
368 );
369 map.insert(
370 "tomorrow-night",
371 ThemeDefinition {
372 id: "tomorrow-night",
373 label: "Tomorrow Night",
374 palette: ThemePalette {
375 primary_accent: RgbColor(0xC5, 0xC8, 0xC6),
376 background: RgbColor(0x1D, 0x1F, 0x21),
377 foreground: RgbColor(0xC5, 0xC8, 0xC6),
378 secondary_accent: RgbColor(0x81, 0xA2, 0xBE),
379 alert: RgbColor(0xCC, 0x66, 0x66),
380 logo_accent: RgbColor(0xDE, 0x93, 0x5F),
381 },
382 },
383 );
384 map.insert(
385 "tomorrow-night-blue",
386 ThemeDefinition {
387 id: "tomorrow-night-blue",
388 label: "Tomorrow Night Blue",
389 palette: ThemePalette {
390 primary_accent: RgbColor(0xFF, 0xFF, 0xFF),
391 background: RgbColor(0x00, 0x2E, 0x4E),
392 foreground: RgbColor(0xFF, 0xFF, 0xFF),
393 secondary_accent: RgbColor(0x7A, 0xBD, 0xFF),
394 alert: RgbColor(0xFF, 0x9D, 0x9D),
395 logo_accent: RgbColor(0xFF, 0xC8, 0x80),
396 },
397 },
398 );
399 map.insert(
400 "tomorrow-night-bright",
401 ThemeDefinition {
402 id: "tomorrow-night-bright",
403 label: "Tomorrow Night Bright",
404 palette: ThemePalette {
405 primary_accent: RgbColor(0xDE, 0xDE, 0xDE),
406 background: RgbColor(0x00, 0x00, 0x00),
407 foreground: RgbColor(0xDE, 0xDE, 0xDE),
408 secondary_accent: RgbColor(0x7A, 0xBD, 0xFF),
409 alert: RgbColor(0xFF, 0x87, 0x87),
410 logo_accent: RgbColor(0xFF, 0xC8, 0x80),
411 },
412 },
413 );
414 map.insert(
415 "tomorrow-night-eighties",
416 ThemeDefinition {
417 id: "tomorrow-night-eighties",
418 label: "Tomorrow Night Eighties",
419 palette: ThemePalette {
420 primary_accent: RgbColor(0xCC, 0xCC, 0xCC),
421 background: RgbColor(0x2D, 0x2D, 0x2D),
422 foreground: RgbColor(0xCC, 0xCC, 0xCC),
423 secondary_accent: RgbColor(0x66, 0x99, 0xCC),
424 alert: RgbColor(0xF2, 0x77, 0x7A),
425 logo_accent: RgbColor(0xF9, 0x91, 0x57),
426 },
427 },
428 );
429 map.insert(
430 "tomorrow-night-burns",
431 ThemeDefinition {
432 id: "tomorrow-night-burns",
433 label: "Tomorrow Night Burns",
434 palette: ThemePalette {
435 primary_accent: RgbColor(0xD0, 0xD0, 0xD0),
436 background: RgbColor(0x15, 0x12, 0x0E),
437 foreground: RgbColor(0xD0, 0xD0, 0xD0),
438 secondary_accent: RgbColor(0x6C, 0x99, 0xB4),
439 alert: RgbColor(0xB7, 0x4E, 0x4E),
440 logo_accent: RgbColor(0xC4, 0x8D, 0x53),
441 },
442 },
443 );
444 map.insert(
445 "material-ocean",
446 ThemeDefinition {
447 id: "material-ocean",
448 label: "Material Ocean",
449 palette: ThemePalette {
450 primary_accent: RgbColor(0xEE, 0xEE, 0xEE),
451 background: RgbColor(0x0F, 0x11, 0x1A),
452 foreground: RgbColor(0xEE, 0xEE, 0xEE),
453 secondary_accent: RgbColor(0x82, 0xAA, 0xFF),
454 alert: RgbColor(0xF0, 0x71, 0x78),
455 logo_accent: RgbColor(0xFF, 0xCB, 0x6B),
456 },
457 },
458 );
459 map.insert(
460 "material-dark",
461 ThemeDefinition {
462 id: "material-dark",
463 label: "Material Dark",
464 palette: ThemePalette {
465 primary_accent: RgbColor(0xEE, 0xEE, 0xEE),
466 background: RgbColor(0x26, 0x32, 0x38),
467 foreground: RgbColor(0xEE, 0xEE, 0xEE),
468 secondary_accent: RgbColor(0x82, 0xAA, 0xFF),
469 alert: RgbColor(0xF0, 0x71, 0x78),
470 logo_accent: RgbColor(0xFF, 0xCB, 0x6B),
471 },
472 },
473 );
474 map.insert(
475 "material",
476 ThemeDefinition {
477 id: "material",
478 label: "Material",
479 palette: ThemePalette {
480 primary_accent: RgbColor(0xEE, 0xEE, 0xEE),
481 background: RgbColor(0x26, 0x32, 0x38),
482 foreground: RgbColor(0xEE, 0xEE, 0xEE),
483 secondary_accent: RgbColor(0x82, 0xAA, 0xFF),
484 alert: RgbColor(0xF0, 0x71, 0x78),
485 logo_accent: RgbColor(0xFF, 0xCB, 0x6B),
486 },
487 },
488 );
489 map.insert(
490 "monokai-classic",
491 ThemeDefinition {
492 id: "monokai-classic",
493 label: "Monokai Classic",
494 palette: ThemePalette {
495 primary_accent: RgbColor(0xF8, 0xF8, 0xF2),
496 background: RgbColor(0x27, 0x28, 0x22),
497 foreground: RgbColor(0xF8, 0xF8, 0xF2),
498 secondary_accent: RgbColor(0x66, 0xD9, 0xEF),
499 alert: RgbColor(0xF9, 0x26, 0x72),
500 logo_accent: RgbColor(0xFD, 0x97, 0x1F),
501 },
502 },
503 );
504 map.insert(
505 "night-owl",
506 ThemeDefinition {
507 id: "night-owl",
508 label: "Night Owl",
509 palette: ThemePalette {
510 primary_accent: RgbColor(0xD6, 0xDE, 0xEB),
511 background: RgbColor(0x01, 0x17, 0x27),
512 foreground: RgbColor(0xD6, 0xDE, 0xEB),
513 secondary_accent: RgbColor(0x82, 0xAA, 0xFF),
514 alert: RgbColor(0xEF, 0x53, 0x50),
515 logo_accent: RgbColor(0xFA, 0xC8, 0x63),
516 },
517 },
518 );
519 map.insert(
520 "zenburn",
521 ThemeDefinition {
522 id: "zenburn",
523 label: "Zenburn",
524 palette: ThemePalette {
525 primary_accent: RgbColor(0xDC, 0xDC, 0xCC),
526 background: RgbColor(0x3F, 0x3F, 0x3F),
527 foreground: RgbColor(0xDC, 0xDC, 0xCC),
528 secondary_accent: RgbColor(0x8C, 0xA8, 0x7D),
529 alert: RgbColor(0xCC, 0x93, 0x93),
530 logo_accent: RgbColor(0xDF, 0xAF, 0x8F),
531 },
532 },
533 );
534 map.insert(
535 "jetbrains-darcula",
536 ThemeDefinition {
537 id: "jetbrains-darcula",
538 label: "JetBrains Darcula",
539 palette: ThemePalette {
540 primary_accent: RgbColor(0xA9, 0xB7, 0xC6),
541 background: RgbColor(0x2B, 0x2B, 0x2B),
542 foreground: RgbColor(0xA9, 0xB7, 0xC6),
543 secondary_accent: RgbColor(0x68, 0x8B, 0xB5),
544 alert: RgbColor(0xCC, 0x78, 0x75),
545 logo_accent: RgbColor(0xBB, 0xA2, 0x6C),
546 },
547 },
548 );
549 map.insert(
550 "spacegray",
551 ThemeDefinition {
552 id: "spacegray",
553 label: "Spacegray",
554 palette: ThemePalette {
555 primary_accent: RgbColor(0xBD, 0xC3, 0xCE),
556 background: RgbColor(0x20, 0x22, 0x2B),
557 foreground: RgbColor(0xBD, 0xC3, 0xCE),
558 secondary_accent: RgbColor(0x7F, 0xA0, 0xC0),
559 alert: RgbColor(0xB0, 0x6B, 0x6B),
560 logo_accent: RgbColor(0xC0, 0x99, 0x70),
561 },
562 },
563 );
564 map.insert(
565 "spacegray-bright",
566 ThemeDefinition {
567 id: "spacegray-bright",
568 label: "Spacegray Bright",
569 palette: ThemePalette {
570 primary_accent: RgbColor(0xF2, 0xF2, 0xF2),
571 background: RgbColor(0x1A, 0x1A, 0x1A),
572 foreground: RgbColor(0xF2, 0xF2, 0xF2),
573 secondary_accent: RgbColor(0x88, 0xB0, 0xD0),
574 alert: RgbColor(0xD0, 0x70, 0x70),
575 logo_accent: RgbColor(0xD0, 0xA0, 0x60),
576 },
577 },
578 );
579 map.insert(
580 "spacegray-eighties",
581 ThemeDefinition {
582 id: "spacegray-eighties",
583 label: "Spacegray Eighties",
584 palette: ThemePalette {
585 primary_accent: RgbColor(0xEC, 0xEC, 0xEC),
586 background: RgbColor(0x22, 0x22, 0x2B),
587 foreground: RgbColor(0xEC, 0xEC, 0xEC),
588 secondary_accent: RgbColor(0x7A, 0x9F, 0xC2),
589 alert: RgbColor(0xC7, 0x6B, 0x6B),
590 logo_accent: RgbColor(0xC2, 0x95, 0x62),
591 },
592 },
593 );
594 map.insert(
595 "spacegray-eighties-dull",
596 ThemeDefinition {
597 id: "spacegray-eighties-dull",
598 label: "Spacegray Eighties Dull",
599 palette: ThemePalette {
600 primary_accent: RgbColor(0xC2, 0xC8, 0xD0),
601 background: RgbColor(0x2D, 0x30, 0x3A),
602 foreground: RgbColor(0xC2, 0xC8, 0xD0),
603 secondary_accent: RgbColor(0x6E, 0x8F, 0xB0),
604 alert: RgbColor(0xB0, 0x6A, 0x6A),
605 logo_accent: RgbColor(0xB0, 0x8C, 0x60),
606 },
607 },
608 );
609 map.insert(
610 "apple-classic",
611 ThemeDefinition {
612 id: "apple-classic",
613 label: "Apple Classic",
614 palette: ThemePalette {
615 primary_accent: RgbColor(0x00, 0x00, 0x00),
616 background: RgbColor(0xF6, 0xF4, 0xEC),
617 foreground: RgbColor(0x00, 0x00, 0x00),
618 secondary_accent: RgbColor(0x00, 0x66, 0x99),
619 alert: RgbColor(0xB0, 0x00, 0x00),
620 logo_accent: RgbColor(0x8B, 0x6F, 0x00),
621 },
622 },
623 );
624 map.insert(
625 "apple-system-colors",
626 ThemeDefinition {
627 id: "apple-system-colors",
628 label: "Apple System Colors",
629 palette: ThemePalette {
630 primary_accent: RgbColor(0xF5, 0xF5, 0xF7),
631 background: RgbColor(0x1C, 0x1C, 0x1E),
632 foreground: RgbColor(0xF5, 0xF5, 0xF7),
633 secondary_accent: RgbColor(0x0A, 0x84, 0xFF),
634 alert: RgbColor(0xFF, 0x45, 0x3A),
635 logo_accent: RgbColor(0xFF, 0x9F, 0x0A),
636 },
637 },
638 );
639 map.insert(
640 "apple-system-colors-light",
641 ThemeDefinition {
642 id: "apple-system-colors-light",
643 label: "Apple System Colors Light",
644 palette: ThemePalette {
645 primary_accent: RgbColor(0x1C, 0x1C, 0x1E),
646 background: RgbColor(0xF5, 0xF5, 0xF7),
647 foreground: RgbColor(0x1C, 0x1C, 0x1E),
648 secondary_accent: RgbColor(0x0A, 0x84, 0xFF),
649 alert: RgbColor(0xFF, 0x3B, 0x30),
650 logo_accent: RgbColor(0xFF, 0x95, 0x00),
651 },
652 },
653 );
654 map.insert(
655 "vitesse-black",
656 ThemeDefinition {
657 id: "vitesse-black",
658 label: "Vitesse Black",
659 palette: ThemePalette {
660 primary_accent: RgbColor(0xDB, 0xD7, 0xCA),
661 background: RgbColor(0x12, 0x12, 0x12),
662 foreground: RgbColor(0xDB, 0xD7, 0xCA),
663 secondary_accent: RgbColor(0x4D, 0x93, 0x8F),
664 alert: RgbColor(0xAB, 0x59, 0x59),
665 logo_accent: RgbColor(0xFF, 0xA6, 0x57),
666 },
667 },
668 );
669 map.insert(
670 "vitesse-dark",
671 ThemeDefinition {
672 id: "vitesse-dark",
673 label: "Vitesse Dark",
674 palette: ThemePalette {
675 primary_accent: RgbColor(0xDB, 0xD7, 0xCA),
676 background: RgbColor(0x18, 0x18, 0x18),
677 foreground: RgbColor(0xDB, 0xD7, 0xCA),
678 secondary_accent: RgbColor(0x4D, 0x93, 0x8F),
679 alert: RgbColor(0xAB, 0x59, 0x59),
680 logo_accent: RgbColor(0xFF, 0xA6, 0x57),
681 },
682 },
683 );
684 map.insert(
685 "vitesse-dark-soft",
686 ThemeDefinition {
687 id: "vitesse-dark-soft",
688 label: "Vitesse Dark Soft",
689 palette: ThemePalette {
690 primary_accent: RgbColor(0xDB, 0xD7, 0xCA),
691 background: RgbColor(0x20, 0x1F, 0x1F),
692 foreground: RgbColor(0xDB, 0xD7, 0xCA),
693 secondary_accent: RgbColor(0x4D, 0x93, 0x8F),
694 alert: RgbColor(0xAB, 0x59, 0x59),
695 logo_accent: RgbColor(0xFF, 0xA6, 0x57),
696 },
697 },
698 );
699 map.insert(
700 "vitesse-light",
701 ThemeDefinition {
702 id: "vitesse-light",
703 label: "Vitesse Light",
704 palette: ThemePalette {
705 primary_accent: RgbColor(0x39, 0x3A, 0x34),
706 background: RgbColor(0xF6, 0xF1, 0xE5),
707 foreground: RgbColor(0x39, 0x3A, 0x34),
708 secondary_accent: RgbColor(0x1C, 0x6B, 0x48),
709 alert: RgbColor(0xAB, 0x59, 0x59),
710 logo_accent: RgbColor(0xB0, 0x70, 0x00),
711 },
712 },
713 );
714 map.insert(
715 "vitesse-light-soft",
716 ThemeDefinition {
717 id: "vitesse-light-soft",
718 label: "Vitesse Light Soft",
719 palette: ThemePalette {
720 primary_accent: RgbColor(0x39, 0x3A, 0x34),
721 background: RgbColor(0xFA, 0xF5, 0xEB),
722 foreground: RgbColor(0x39, 0x3A, 0x34),
723 secondary_accent: RgbColor(0x1C, 0x6B, 0x48),
724 alert: RgbColor(0xAB, 0x59, 0x59),
725 logo_accent: RgbColor(0xB0, 0x70, 0x00),
726 },
727 },
728 );
729 map.insert(
730 "homebrew",
731 ThemeDefinition {
732 id: "homebrew",
733 label: "Homebrew",
734 palette: ThemePalette {
735 primary_accent: RgbColor(0xCC, 0xCC, 0xCC),
736 background: RgbColor(0x00, 0x00, 0x00),
737 foreground: RgbColor(0xCC, 0xCC, 0xCC),
738 secondary_accent: RgbColor(0x00, 0x99, 0xCC),
739 alert: RgbColor(0xCC, 0x33, 0x33),
740 logo_accent: RgbColor(0xCC, 0x99, 0x00),
741 },
742 },
743 );
744 map.insert(
745 "man-page",
746 ThemeDefinition {
747 id: "man-page",
748 label: "Man Page",
749 palette: ThemePalette {
750 primary_accent: RgbColor(0x00, 0x00, 0x00),
751 background: RgbColor(0xF2, 0xF2, 0xE6),
752 foreground: RgbColor(0x00, 0x00, 0x00),
753 secondary_accent: RgbColor(0x00, 0x66, 0x66),
754 alert: RgbColor(0x99, 0x00, 0x00),
755 logo_accent: RgbColor(0x7A, 0x5D, 0x00),
756 },
757 },
758 );
759 map.insert(
760 "framer",
761 ThemeDefinition {
762 id: "framer",
763 label: "Framer",
764 palette: ThemePalette {
765 primary_accent: RgbColor(0xF5, 0xF5, 0xF5),
766 background: RgbColor(0x10, 0x10, 0x10),
767 foreground: RgbColor(0xF5, 0xF5, 0xF5),
768 secondary_accent: RgbColor(0x7A, 0x5A, 0xFF),
769 alert: RgbColor(0xFF, 0x5C, 0x5C),
770 logo_accent: RgbColor(0xFF, 0xAF, 0x3F),
771 },
772 },
773 );
774 map.insert(
775 "espresso",
776 ThemeDefinition {
777 id: "espresso",
778 label: "Espresso",
779 palette: ThemePalette {
780 primary_accent: RgbColor(0xD0, 0xC8, 0xB8),
781 background: RgbColor(0x2A, 0x21, 0x1C),
782 foreground: RgbColor(0xD0, 0xC8, 0xB8),
783 secondary_accent: RgbColor(0x6F, 0xB3, 0xC2),
784 alert: RgbColor(0xD2, 0x52, 0x52),
785 logo_accent: RgbColor(0xC8, 0x92, 0x2D),
786 },
787 },
788 );
789 map.insert(
790 "adventure-time",
791 ThemeDefinition {
792 id: "adventure-time",
793 label: "Adventure Time",
794 palette: ThemePalette {
795 primary_accent: RgbColor(0xF8, 0xF8, 0xF8),
796 background: RgbColor(0x1F, 0x1D, 0x45),
797 foreground: RgbColor(0xF8, 0xF8, 0xF8),
798 secondary_accent: RgbColor(0x8A, 0x9B, 0xFF),
799 alert: RgbColor(0xD7, 0x56, 0x56),
800 logo_accent: RgbColor(0xF5, 0xB8, 0x4A),
801 },
802 },
803 );
804 map.insert(
805 "afterglow",
806 ThemeDefinition {
807 id: "afterglow",
808 label: "Afterglow",
809 palette: ThemePalette {
810 primary_accent: RgbColor(0xD6, 0xD6, 0xD6),
811 background: RgbColor(0x22, 0x22, 0x22),
812 foreground: RgbColor(0xD6, 0xD6, 0xD6),
813 secondary_accent: RgbColor(0x7F, 0xB0, 0xD0),
814 alert: RgbColor(0xE5, 0x72, 0x72),
815 logo_accent: RgbColor(0xD0, 0xA0, 0x60),
816 },
817 },
818 );
819 map.insert(
820 "mono",
821 ThemeDefinition {
822 id: "mono",
823 label: "Mono",
824 palette: ThemePalette {
825 primary_accent: RgbColor(0xFF, 0xFF, 0xFF),
826 background: RgbColor(0x00, 0x00, 0x00),
827 foreground: RgbColor(0xDB, 0xD7, 0xCA),
828 secondary_accent: RgbColor(0xBB, 0xBB, 0xBB),
829 alert: RgbColor(0xFF, 0xFF, 0xFF),
830 logo_accent: RgbColor(0xFF, 0xFF, 0xFF),
831 },
832 },
833 );
834 map.insert(
835 "ansi-classic",
836 ThemeDefinition {
837 id: "ansi-classic",
838 label: "ANSI Classic",
839 palette: ThemePalette {
840 primary_accent: RgbColor(0xC0, 0xC0, 0xC0),
841 background: RgbColor(0x00, 0x00, 0x00),
842 foreground: RgbColor(0xC0, 0xC0, 0xC0),
843 secondary_accent: RgbColor(0x00, 0xAA, 0xAA),
844 alert: RgbColor(0xAA, 0x00, 0x00),
845 logo_accent: RgbColor(0xAA, 0xAA, 0x00),
846 },
847 },
848 );
849
850 register_catppuccin_themes(&mut map);
851 map
852});
853
854fn register_catppuccin_themes(map: &mut HashMap<&'static str, ThemeDefinition>) {
855 for &flavor_kind in CATPPUCCIN_FLAVORS {
856 let flavor = flavor_kind.flavor();
857 map.insert(
858 flavor_kind.id(),
859 ThemeDefinition {
860 id: flavor_kind.id(),
861 label: flavor_kind.label(),
862 palette: catppuccin_palette(flavor),
863 },
864 );
865 }
866}
867
868fn catppuccin_palette(flavor: catppuccin::Flavor) -> ThemePalette {
869 let colors = flavor.colors;
870 ThemePalette {
871 primary_accent: catppuccin_rgb(colors.lavender),
872 background: catppuccin_rgb(colors.base),
873 foreground: catppuccin_rgb(colors.text),
874 secondary_accent: catppuccin_rgb(colors.sapphire),
875 alert: catppuccin_rgb(colors.red),
876 logo_accent: catppuccin_rgb(colors.peach),
877 }
878}
879
880fn catppuccin_rgb(color: catppuccin::Color) -> RgbColor {
881 RgbColor(color.rgb.r, color.rgb.g, color.rgb.b)
882}
883
884pub(crate) fn theme_definition(theme_id: &str) -> Option<&'static ThemeDefinition> {
885 REGISTRY.get(theme_id)
886}
887
888#[cfg(test)]
889pub(crate) fn all_theme_definitions() -> &'static HashMap<&'static str, ThemeDefinition> {
890 ®ISTRY
891}
892
893pub fn available_themes() -> Vec<&'static str> {
895 let mut keys: Vec<_> = REGISTRY.keys().copied().collect();
896 keys.sort();
897 keys
898}
899
900pub fn theme_label(theme_id: &str) -> Option<&'static str> {
902 theme_definition(theme_id).map(|definition| definition.label)
903}
904
905fn suite_id_for_theme(theme_id: &str) -> Option<&'static str> {
906 if theme_id.starts_with("catppuccin-") {
907 Some("catppuccin")
908 } else if theme_id.starts_with("vitesse-") {
909 Some("vitesse")
910 } else if theme_id.starts_with("ciapre-") {
911 Some("ciapre")
912 } else if theme_id == "mono" {
913 Some("mono")
914 } else {
915 None
916 }
917}
918
919fn suite_label(suite_id: &str) -> Option<&'static str> {
920 match suite_id {
921 "catppuccin" => Some("Catppuccin"),
922 "vitesse" => Some("Vitesse"),
923 "ciapre" => Some("Ciapre"),
924 "mono" => Some("Mono"),
925 _ => None,
926 }
927}
928
929pub fn theme_suite_id(theme_id: &str) -> Option<&'static str> {
931 suite_id_for_theme(theme_id)
932}
933
934pub fn theme_suite_label(theme_id: &str) -> Option<&'static str> {
936 suite_id_for_theme(theme_id).and_then(suite_label)
937}
938
939pub fn available_theme_suites() -> Vec<ThemeSuite> {
941 const ORDER: &[&str] = &["ciapre", "vitesse", "catppuccin", "mono"];
942
943 ORDER
944 .iter()
945 .filter_map(|suite_id| {
946 let mut theme_ids: Vec<&'static str> = available_themes()
947 .into_iter()
948 .filter(|theme_id| suite_id_for_theme(theme_id) == Some(*suite_id))
949 .collect();
950 if theme_ids.is_empty() {
951 return None;
952 }
953 theme_ids.sort_unstable();
954 Some(ThemeSuite {
955 id: suite_id,
956 label: suite_label(suite_id)?,
957 theme_ids,
958 })
959 })
960 .collect()
961}