1use super::types::{AppTheme, Rgb};
9
10pub const THEME_NAMES: &[&str] = &[
14 "Default",
15 "Grape",
16 "Ocean",
17 "Sunset",
18 "Forest",
19 "Rose",
20 "Mono",
21 "Neon",
22 "Dracula",
23 "Nord",
24 "Solarized Dark",
25 "Solarized Light",
26 "Gruvbox Dark",
27 "Gruvbox Light",
28 "Catppuccin Latte",
29 "Catppuccin Frappé",
30 "Catppuccin Macchiato",
31 "Catppuccin Mocha",
32 "Tokyo Night",
33 "Tokyo Night Storm",
34 "Tokyo Night Light",
35 "Kanagawa Wave",
36 "Kanagawa Dragon",
37 "Kanagawa Lotus",
38 "Moonfly",
39 "Nightfly",
40 "Oxocarbon",
41];
42
43pub const THEME_COUNT: usize = 27;
45
46pub fn theme_by_index(index: usize) -> AppTheme {
48 match index {
49 0 => default(),
50 1 => grape(),
51 2 => ocean(),
52 3 => sunset(),
53 4 => forest(),
54 5 => rose(),
55 6 => mono(),
56 7 => neon(),
57 8 => dracula(),
58 9 => nord(),
59 10 => solarized_dark(),
60 11 => solarized_light(),
61 12 => gruvbox_dark(),
62 13 => gruvbox_light(),
63 14 => catppuccin_latte(),
64 15 => catppuccin_frappe(),
65 16 => catppuccin_macchiato(),
66 17 => catppuccin_mocha(),
67 18 => tokyo_night(),
68 19 => tokyo_night_storm(),
69 20 => tokyo_night_light(),
70 21 => kanagawa_wave(),
71 22 => kanagawa_dragon(),
72 23 => kanagawa_lotus(),
73 24 => moonfly(),
74 25 => nightfly(),
75 26 => oxocarbon(),
76 _ => default(),
77 }
78}
79
80pub fn theme_index_by_name(name: &str) -> usize {
83 THEME_NAMES
84 .iter()
85 .position(|n| n.eq_ignore_ascii_case(name))
86 .unwrap_or(0)
87}
88
89pub fn default() -> AppTheme {
92 AppTheme {
93 is_dark: true,
94 background: Rgb::new(13, 17, 23),
95 surface: Rgb::new(22, 27, 34),
96 border: Rgb::new(48, 54, 61),
97 selection: Rgb::new(40, 60, 80),
98 text_primary: Rgb::new(230, 237, 243),
99 text_secondary: Rgb::new(139, 148, 158),
100 text_muted: Rgb::new(72, 79, 88),
101 accent: Rgb::new(88, 166, 255),
102 success: Rgb::new(63, 185, 80),
103 warning: Rgb::new(210, 154, 34),
104 error: Rgb::new(248, 83, 73),
105 diff_add: Rgb::new(63, 185, 80),
106 diff_del: Rgb::new(248, 83, 73),
107 diff_context: Rgb::new(139, 148, 158),
108 diff_hunk: Rgb::new(88, 166, 255),
109 graph_colors: [
110 Rgb::new(88, 166, 255),
111 Rgb::new(63, 185, 80),
112 Rgb::new(248, 83, 73),
113 Rgb::new(210, 154, 34),
114 Rgb::new(188, 140, 255),
115 Rgb::new(0, 200, 180),
116 Rgb::new(255, 140, 60),
117 Rgb::new(255, 130, 160),
118 ],
119 }
120}
121
122pub fn grape() -> AppTheme {
123 AppTheme {
124 is_dark: true,
125 background: Rgb::new(24, 18, 36),
126 surface: Rgb::new(35, 28, 50),
127 border: Rgb::new(60, 50, 80),
128 selection: Rgb::new(50, 40, 70),
129 text_primary: Rgb::new(220, 210, 240),
130 text_secondary: Rgb::new(160, 140, 200),
131 text_muted: Rgb::new(100, 85, 130),
132 accent: Rgb::new(180, 130, 255),
133 success: Rgb::new(130, 230, 160),
134 warning: Rgb::new(240, 200, 100),
135 error: Rgb::new(255, 100, 120),
136 diff_add: Rgb::new(130, 230, 160),
137 diff_del: Rgb::new(255, 100, 120),
138 diff_context: Rgb::new(100, 85, 130),
139 diff_hunk: Rgb::new(150, 160, 255),
140 graph_colors: [
141 Rgb::new(180, 130, 255),
142 Rgb::new(130, 230, 160),
143 Rgb::new(255, 100, 120),
144 Rgb::new(240, 200, 100),
145 Rgb::new(100, 180, 255),
146 Rgb::new(255, 160, 200),
147 Rgb::new(120, 220, 220),
148 Rgb::new(255, 170, 100),
149 ],
150 }
151}
152
153pub fn ocean() -> AppTheme {
154 AppTheme {
155 is_dark: true,
156 background: Rgb::new(15, 25, 35),
157 surface: Rgb::new(22, 35, 48),
158 border: Rgb::new(40, 60, 80),
159 selection: Rgb::new(30, 55, 75),
160 text_primary: Rgb::new(200, 220, 240),
161 text_secondary: Rgb::new(100, 170, 200),
162 text_muted: Rgb::new(70, 100, 130),
163 accent: Rgb::new(80, 200, 180),
164 success: Rgb::new(80, 220, 120),
165 warning: Rgb::new(220, 200, 80),
166 error: Rgb::new(255, 100, 100),
167 diff_add: Rgb::new(80, 220, 120),
168 diff_del: Rgb::new(255, 100, 100),
169 diff_context: Rgb::new(70, 100, 130),
170 diff_hunk: Rgb::new(80, 200, 180),
171 graph_colors: [
172 Rgb::new(80, 200, 180),
173 Rgb::new(80, 220, 120),
174 Rgb::new(255, 100, 100),
175 Rgb::new(220, 200, 80),
176 Rgb::new(100, 160, 255),
177 Rgb::new(200, 130, 255),
178 Rgb::new(255, 180, 80),
179 Rgb::new(255, 130, 180),
180 ],
181 }
182}
183
184pub fn sunset() -> AppTheme {
185 AppTheme {
186 is_dark: true,
187 background: Rgb::new(35, 18, 18),
188 surface: Rgb::new(50, 28, 28),
189 border: Rgb::new(80, 45, 45),
190 selection: Rgb::new(70, 35, 35),
191 text_primary: Rgb::new(240, 220, 210),
192 text_secondary: Rgb::new(200, 150, 120),
193 text_muted: Rgb::new(140, 100, 80),
194 accent: Rgb::new(255, 140, 60),
195 success: Rgb::new(180, 220, 80),
196 warning: Rgb::new(255, 200, 50),
197 error: Rgb::new(255, 80, 80),
198 diff_add: Rgb::new(180, 220, 80),
199 diff_del: Rgb::new(255, 80, 80),
200 diff_context: Rgb::new(140, 100, 80),
201 diff_hunk: Rgb::new(255, 180, 100),
202 graph_colors: [
203 Rgb::new(255, 140, 60),
204 Rgb::new(180, 220, 80),
205 Rgb::new(255, 80, 80),
206 Rgb::new(255, 200, 50),
207 Rgb::new(200, 120, 255),
208 Rgb::new(80, 200, 200),
209 Rgb::new(255, 130, 160),
210 Rgb::new(100, 180, 255),
211 ],
212 }
213}
214
215pub fn forest() -> AppTheme {
216 AppTheme {
217 is_dark: true,
218 background: Rgb::new(18, 28, 18),
219 surface: Rgb::new(28, 40, 28),
220 border: Rgb::new(50, 70, 50),
221 selection: Rgb::new(35, 55, 35),
222 text_primary: Rgb::new(210, 230, 210),
223 text_secondary: Rgb::new(140, 180, 140),
224 text_muted: Rgb::new(80, 110, 80),
225 accent: Rgb::new(80, 180, 80),
226 success: Rgb::new(100, 220, 100),
227 warning: Rgb::new(220, 200, 80),
228 error: Rgb::new(220, 90, 70),
229 diff_add: Rgb::new(100, 220, 100),
230 diff_del: Rgb::new(220, 90, 70),
231 diff_context: Rgb::new(80, 110, 80),
232 diff_hunk: Rgb::new(120, 180, 120),
233 graph_colors: [
234 Rgb::new(80, 180, 80),
235 Rgb::new(100, 220, 100),
236 Rgb::new(220, 90, 70),
237 Rgb::new(220, 200, 80),
238 Rgb::new(100, 170, 220),
239 Rgb::new(180, 130, 200),
240 Rgb::new(200, 180, 100),
241 Rgb::new(140, 210, 200),
242 ],
243 }
244}
245
246pub fn rose() -> AppTheme {
247 AppTheme {
248 is_dark: true,
249 background: Rgb::new(30, 18, 25),
250 surface: Rgb::new(45, 28, 38),
251 border: Rgb::new(75, 45, 60),
252 selection: Rgb::new(60, 35, 50),
253 text_primary: Rgb::new(240, 220, 230),
254 text_secondary: Rgb::new(200, 140, 170),
255 text_muted: Rgb::new(130, 90, 110),
256 accent: Rgb::new(255, 130, 160),
257 success: Rgb::new(130, 220, 150),
258 warning: Rgb::new(240, 200, 100),
259 error: Rgb::new(255, 80, 100),
260 diff_add: Rgb::new(130, 220, 150),
261 diff_del: Rgb::new(255, 80, 100),
262 diff_context: Rgb::new(130, 90, 110),
263 diff_hunk: Rgb::new(220, 150, 200),
264 graph_colors: [
265 Rgb::new(255, 130, 160),
266 Rgb::new(130, 220, 150),
267 Rgb::new(255, 80, 100),
268 Rgb::new(240, 200, 100),
269 Rgb::new(130, 170, 255),
270 Rgb::new(200, 140, 255),
271 Rgb::new(80, 210, 210),
272 Rgb::new(255, 170, 100),
273 ],
274 }
275}
276
277pub fn mono() -> AppTheme {
278 AppTheme {
279 is_dark: true,
280 background: Rgb::new(20, 20, 20),
281 surface: Rgb::new(35, 35, 35),
282 border: Rgb::new(60, 60, 60),
283 selection: Rgb::new(50, 50, 50),
284 text_primary: Rgb::new(220, 220, 220),
285 text_secondary: Rgb::new(160, 160, 160),
286 text_muted: Rgb::new(100, 100, 100),
287 accent: Rgb::new(180, 180, 180),
288 success: Rgb::new(180, 220, 180),
289 warning: Rgb::new(220, 200, 160),
290 error: Rgb::new(220, 140, 140),
291 diff_add: Rgb::new(180, 220, 180),
292 diff_del: Rgb::new(220, 140, 140),
293 diff_context: Rgb::new(100, 100, 100),
294 diff_hunk: Rgb::new(180, 180, 180),
295 graph_colors: [
296 Rgb::new(180, 180, 180),
297 Rgb::new(180, 220, 180),
298 Rgb::new(220, 140, 140),
299 Rgb::new(220, 200, 160),
300 Rgb::new(140, 180, 220),
301 Rgb::new(200, 160, 200),
302 Rgb::new(200, 200, 140),
303 Rgb::new(160, 210, 210),
304 ],
305 }
306}
307
308pub fn neon() -> AppTheme {
309 AppTheme {
310 is_dark: true,
311 background: Rgb::new(10, 10, 18),
312 surface: Rgb::new(18, 18, 30),
313 border: Rgb::new(30, 30, 60),
314 selection: Rgb::new(25, 25, 50),
315 text_primary: Rgb::new(220, 240, 255),
316 text_secondary: Rgb::new(0, 200, 255),
317 text_muted: Rgb::new(60, 80, 120),
318 accent: Rgb::new(0, 255, 200),
319 success: Rgb::new(0, 255, 100),
320 warning: Rgb::new(255, 255, 0),
321 error: Rgb::new(255, 0, 80),
322 diff_add: Rgb::new(0, 255, 100),
323 diff_del: Rgb::new(255, 0, 80),
324 diff_context: Rgb::new(60, 80, 120),
325 diff_hunk: Rgb::new(200, 0, 255),
326 graph_colors: [
327 Rgb::new(0, 255, 200),
328 Rgb::new(0, 255, 100),
329 Rgb::new(255, 0, 80),
330 Rgb::new(255, 255, 0),
331 Rgb::new(0, 200, 255),
332 Rgb::new(200, 0, 255),
333 Rgb::new(255, 100, 0),
334 Rgb::new(255, 0, 200),
335 ],
336 }
337}
338
339pub fn dracula() -> AppTheme {
340 AppTheme {
341 is_dark: true,
342 background: Rgb::new(40, 42, 54),
343 surface: Rgb::new(68, 71, 90),
344 border: Rgb::new(98, 114, 164),
345 selection: Rgb::new(68, 71, 90),
346 text_primary: Rgb::new(248, 248, 242),
347 text_secondary: Rgb::new(189, 147, 249),
348 text_muted: Rgb::new(98, 114, 164),
349 accent: Rgb::new(189, 147, 249),
350 success: Rgb::new(80, 250, 123),
351 warning: Rgb::new(241, 250, 140),
352 error: Rgb::new(255, 85, 85),
353 diff_add: Rgb::new(80, 250, 123),
354 diff_del: Rgb::new(255, 85, 85),
355 diff_context: Rgb::new(98, 114, 164),
356 diff_hunk: Rgb::new(139, 233, 253),
357 graph_colors: [
358 Rgb::new(189, 147, 249),
359 Rgb::new(80, 250, 123),
360 Rgb::new(255, 85, 85),
361 Rgb::new(241, 250, 140),
362 Rgb::new(139, 233, 253),
363 Rgb::new(255, 121, 198),
364 Rgb::new(255, 184, 108),
365 Rgb::new(98, 114, 164),
366 ],
367 }
368}
369
370pub fn nord() -> AppTheme {
371 AppTheme {
372 is_dark: true,
373 background: Rgb::new(46, 52, 64),
374 surface: Rgb::new(59, 66, 82),
375 border: Rgb::new(76, 86, 106),
376 selection: Rgb::new(59, 66, 82),
377 text_primary: Rgb::new(216, 222, 233),
378 text_secondary: Rgb::new(129, 161, 193),
379 text_muted: Rgb::new(76, 86, 106),
380 accent: Rgb::new(136, 192, 208),
381 success: Rgb::new(163, 190, 140),
382 warning: Rgb::new(235, 203, 139),
383 error: Rgb::new(191, 97, 106),
384 diff_add: Rgb::new(163, 190, 140),
385 diff_del: Rgb::new(191, 97, 106),
386 diff_context: Rgb::new(76, 86, 106),
387 diff_hunk: Rgb::new(129, 161, 193),
388 graph_colors: [
389 Rgb::new(136, 192, 208),
390 Rgb::new(163, 190, 140),
391 Rgb::new(191, 97, 106),
392 Rgb::new(235, 203, 139),
393 Rgb::new(129, 161, 193),
394 Rgb::new(180, 142, 173),
395 Rgb::new(208, 135, 112),
396 Rgb::new(143, 188, 187),
397 ],
398 }
399}
400
401pub fn solarized_dark() -> AppTheme {
402 AppTheme {
403 is_dark: true,
404 background: Rgb::new(0, 43, 54),
405 surface: Rgb::new(7, 54, 66),
406 border: Rgb::new(88, 110, 117),
407 selection: Rgb::new(7, 54, 66),
408 text_primary: Rgb::new(131, 148, 150),
409 text_secondary: Rgb::new(42, 161, 152),
410 text_muted: Rgb::new(88, 110, 117),
411 accent: Rgb::new(38, 139, 210),
412 success: Rgb::new(133, 153, 0),
413 warning: Rgb::new(181, 137, 0),
414 error: Rgb::new(220, 50, 47),
415 diff_add: Rgb::new(133, 153, 0),
416 diff_del: Rgb::new(220, 50, 47),
417 diff_context: Rgb::new(88, 110, 117),
418 diff_hunk: Rgb::new(42, 161, 152),
419 graph_colors: [
420 Rgb::new(38, 139, 210),
421 Rgb::new(133, 153, 0),
422 Rgb::new(220, 50, 47),
423 Rgb::new(181, 137, 0),
424 Rgb::new(42, 161, 152),
425 Rgb::new(108, 113, 196),
426 Rgb::new(203, 75, 22),
427 Rgb::new(211, 54, 130),
428 ],
429 }
430}
431
432pub fn solarized_light() -> AppTheme {
433 AppTheme {
434 is_dark: false,
435 background: Rgb::new(253, 246, 227),
436 surface: Rgb::new(238, 232, 213),
437 border: Rgb::new(147, 161, 161),
438 selection: Rgb::new(238, 232, 213),
439 text_primary: Rgb::new(101, 123, 131),
440 text_secondary: Rgb::new(42, 161, 152),
441 text_muted: Rgb::new(147, 161, 161),
442 accent: Rgb::new(38, 139, 210),
443 success: Rgb::new(133, 153, 0),
444 warning: Rgb::new(181, 137, 0),
445 error: Rgb::new(220, 50, 47),
446 diff_add: Rgb::new(133, 153, 0),
447 diff_del: Rgb::new(220, 50, 47),
448 diff_context: Rgb::new(147, 161, 161),
449 diff_hunk: Rgb::new(42, 161, 152),
450 graph_colors: [
451 Rgb::new(38, 139, 210),
452 Rgb::new(133, 153, 0),
453 Rgb::new(220, 50, 47),
454 Rgb::new(181, 137, 0),
455 Rgb::new(42, 161, 152),
456 Rgb::new(108, 113, 196),
457 Rgb::new(203, 75, 22),
458 Rgb::new(211, 54, 130),
459 ],
460 }
461}
462
463pub fn gruvbox_dark() -> AppTheme {
464 AppTheme {
465 is_dark: true,
466 background: Rgb::new(40, 40, 40),
467 surface: Rgb::new(60, 56, 54),
468 border: Rgb::new(80, 73, 69),
469 selection: Rgb::new(60, 56, 54),
470 text_primary: Rgb::new(235, 219, 178),
471 text_secondary: Rgb::new(250, 189, 47),
472 text_muted: Rgb::new(146, 131, 116),
473 accent: Rgb::new(254, 128, 25),
474 success: Rgb::new(184, 187, 38),
475 warning: Rgb::new(250, 189, 47),
476 error: Rgb::new(251, 73, 52),
477 diff_add: Rgb::new(184, 187, 38),
478 diff_del: Rgb::new(251, 73, 52),
479 diff_context: Rgb::new(146, 131, 116),
480 diff_hunk: Rgb::new(142, 192, 124),
481 graph_colors: [
482 Rgb::new(254, 128, 25),
483 Rgb::new(184, 187, 38),
484 Rgb::new(251, 73, 52),
485 Rgb::new(250, 189, 47),
486 Rgb::new(131, 165, 152),
487 Rgb::new(211, 134, 155),
488 Rgb::new(142, 192, 124),
489 Rgb::new(69, 133, 136),
490 ],
491 }
492}
493
494pub fn gruvbox_light() -> AppTheme {
495 AppTheme {
496 is_dark: false,
497 background: Rgb::new(251, 241, 199),
498 surface: Rgb::new(213, 196, 161),
499 border: Rgb::new(168, 153, 132),
500 selection: Rgb::new(213, 196, 161),
501 text_primary: Rgb::new(60, 56, 54),
502 text_secondary: Rgb::new(215, 153, 33),
503 text_muted: Rgb::new(146, 131, 116),
504 accent: Rgb::new(214, 93, 14),
505 success: Rgb::new(121, 116, 14),
506 warning: Rgb::new(215, 153, 33),
507 error: Rgb::new(157, 0, 6),
508 diff_add: Rgb::new(121, 116, 14),
509 diff_del: Rgb::new(157, 0, 6),
510 diff_context: Rgb::new(146, 131, 116),
511 diff_hunk: Rgb::new(104, 157, 106),
512 graph_colors: [
513 Rgb::new(214, 93, 14),
514 Rgb::new(121, 116, 14),
515 Rgb::new(157, 0, 6),
516 Rgb::new(215, 153, 33),
517 Rgb::new(69, 133, 136),
518 Rgb::new(177, 98, 134),
519 Rgb::new(104, 157, 106),
520 Rgb::new(7, 102, 120),
521 ],
522 }
523}
524
525pub fn catppuccin_latte() -> AppTheme {
526 AppTheme {
527 is_dark: false,
528 background: Rgb::new(239, 241, 245),
530 surface: Rgb::new(204, 208, 218),
532 border: Rgb::new(172, 176, 190),
534 selection: Rgb::new(188, 192, 204),
536 text_primary: Rgb::new(76, 79, 105),
538 text_secondary: Rgb::new(92, 95, 119),
540 text_muted: Rgb::new(156, 160, 176),
542 accent: Rgb::new(136, 57, 239),
544 success: Rgb::new(64, 160, 43),
546 warning: Rgb::new(223, 142, 29),
548 error: Rgb::new(210, 15, 57),
550 diff_add: Rgb::new(64, 160, 43),
551 diff_del: Rgb::new(210, 15, 57),
552 diff_context: Rgb::new(156, 160, 176),
554 diff_hunk: Rgb::new(23, 146, 153),
556 graph_colors: [
557 Rgb::new(136, 57, 239), Rgb::new(64, 160, 43), Rgb::new(210, 15, 57), Rgb::new(223, 142, 29), Rgb::new(23, 146, 153), Rgb::new(30, 102, 245), Rgb::new(230, 69, 83), Rgb::new(32, 159, 181), ],
566 }
567}
568
569pub fn catppuccin_frappe() -> AppTheme {
570 AppTheme {
571 is_dark: true,
572 background: Rgb::new(48, 52, 70),
574 surface: Rgb::new(65, 69, 89),
576 border: Rgb::new(98, 104, 128),
578 selection: Rgb::new(81, 87, 109),
580 text_primary: Rgb::new(198, 208, 245),
582 text_secondary: Rgb::new(181, 191, 226),
584 text_muted: Rgb::new(115, 121, 148),
586 accent: Rgb::new(202, 158, 230),
588 success: Rgb::new(166, 209, 137),
590 warning: Rgb::new(229, 200, 144),
592 error: Rgb::new(231, 130, 132),
594 diff_add: Rgb::new(166, 209, 137),
595 diff_del: Rgb::new(231, 130, 132),
596 diff_context: Rgb::new(115, 121, 148),
598 diff_hunk: Rgb::new(129, 200, 190),
600 graph_colors: [
601 Rgb::new(202, 158, 230), Rgb::new(166, 209, 137), Rgb::new(231, 130, 132), Rgb::new(229, 200, 144), Rgb::new(140, 170, 238), Rgb::new(244, 184, 228), Rgb::new(129, 200, 190), Rgb::new(239, 159, 118), ],
610 }
611}
612
613pub fn catppuccin_macchiato() -> AppTheme {
614 AppTheme {
615 is_dark: true,
616 background: Rgb::new(36, 39, 58),
618 surface: Rgb::new(54, 58, 79),
620 border: Rgb::new(91, 96, 120),
622 selection: Rgb::new(73, 77, 100),
624 text_primary: Rgb::new(202, 211, 245),
626 text_secondary: Rgb::new(184, 192, 224),
628 text_muted: Rgb::new(110, 115, 141),
630 accent: Rgb::new(198, 160, 246),
632 success: Rgb::new(166, 218, 149),
634 warning: Rgb::new(238, 212, 159),
636 error: Rgb::new(237, 135, 150),
638 diff_add: Rgb::new(166, 218, 149),
639 diff_del: Rgb::new(237, 135, 150),
640 diff_context: Rgb::new(110, 115, 141),
642 diff_hunk: Rgb::new(139, 213, 202),
644 graph_colors: [
645 Rgb::new(198, 160, 246), Rgb::new(166, 218, 149), Rgb::new(237, 135, 150), Rgb::new(238, 212, 159), Rgb::new(138, 173, 244), Rgb::new(245, 189, 230), Rgb::new(139, 213, 202), Rgb::new(245, 169, 127), ],
654 }
655}
656
657pub fn catppuccin_mocha() -> AppTheme {
658 AppTheme {
659 is_dark: true,
660 background: Rgb::new(30, 30, 46),
662 surface: Rgb::new(49, 50, 68),
664 border: Rgb::new(88, 91, 112),
666 selection: Rgb::new(69, 71, 90),
668 text_primary: Rgb::new(205, 214, 244),
670 text_secondary: Rgb::new(186, 194, 222),
672 text_muted: Rgb::new(108, 112, 134),
674 accent: Rgb::new(203, 166, 247),
676 success: Rgb::new(166, 227, 161),
678 warning: Rgb::new(249, 226, 175),
680 error: Rgb::new(243, 139, 168),
682 diff_add: Rgb::new(166, 227, 161),
683 diff_del: Rgb::new(243, 139, 168),
684 diff_context: Rgb::new(108, 112, 134),
686 diff_hunk: Rgb::new(137, 180, 250),
688 graph_colors: [
689 Rgb::new(203, 166, 247), Rgb::new(166, 227, 161), Rgb::new(243, 139, 168), Rgb::new(249, 226, 175), Rgb::new(137, 180, 250), Rgb::new(245, 194, 231), Rgb::new(148, 226, 213), Rgb::new(250, 179, 135), ],
698 }
699}
700
701pub fn tokyo_night() -> AppTheme {
702 AppTheme {
703 is_dark: true,
704 background: Rgb::new(26, 27, 38),
705 surface: Rgb::new(41, 46, 66),
706 border: Rgb::new(59, 66, 97),
707 selection: Rgb::new(41, 46, 66),
708 text_primary: Rgb::new(192, 202, 245),
709 text_secondary: Rgb::new(122, 162, 247),
710 text_muted: Rgb::new(86, 95, 137),
711 accent: Rgb::new(122, 162, 247),
712 success: Rgb::new(158, 206, 106),
713 warning: Rgb::new(224, 175, 104),
714 error: Rgb::new(247, 118, 142),
715 diff_add: Rgb::new(158, 206, 106),
716 diff_del: Rgb::new(247, 118, 142),
717 diff_context: Rgb::new(86, 95, 137),
718 diff_hunk: Rgb::new(187, 154, 247),
719 graph_colors: [
720 Rgb::new(122, 162, 247),
721 Rgb::new(158, 206, 106),
722 Rgb::new(247, 118, 142),
723 Rgb::new(224, 175, 104),
724 Rgb::new(187, 154, 247),
725 Rgb::new(255, 117, 127),
726 Rgb::new(115, 218, 202),
727 Rgb::new(255, 158, 100),
728 ],
729 }
730}
731
732pub fn tokyo_night_storm() -> AppTheme {
733 AppTheme {
734 is_dark: true,
735 background: Rgb::new(36, 40, 59),
736 surface: Rgb::new(45, 49, 75),
737 border: Rgb::new(59, 66, 97),
738 selection: Rgb::new(45, 49, 75),
739 text_primary: Rgb::new(192, 202, 245),
740 text_secondary: Rgb::new(122, 162, 247),
741 text_muted: Rgb::new(86, 95, 137),
742 accent: Rgb::new(122, 162, 247),
743 success: Rgb::new(158, 206, 106),
744 warning: Rgb::new(224, 175, 104),
745 error: Rgb::new(247, 118, 142),
746 diff_add: Rgb::new(158, 206, 106),
747 diff_del: Rgb::new(247, 118, 142),
748 diff_context: Rgb::new(86, 95, 137),
749 diff_hunk: Rgb::new(187, 154, 247),
750 graph_colors: [
751 Rgb::new(122, 162, 247),
752 Rgb::new(158, 206, 106),
753 Rgb::new(247, 118, 142),
754 Rgb::new(224, 175, 104),
755 Rgb::new(187, 154, 247),
756 Rgb::new(255, 117, 127),
757 Rgb::new(115, 218, 202),
758 Rgb::new(255, 158, 100),
759 ],
760 }
761}
762
763pub fn tokyo_night_light() -> AppTheme {
764 AppTheme {
765 is_dark: false,
766 background: Rgb::new(213, 214, 219),
767 surface: Rgb::new(208, 213, 227),
768 border: Rgb::new(132, 140, 176),
769 selection: Rgb::new(208, 213, 227),
770 text_primary: Rgb::new(52, 59, 88),
771 text_secondary: Rgb::new(46, 126, 233),
772 text_muted: Rgb::new(132, 140, 176),
773 accent: Rgb::new(46, 126, 233),
774 success: Rgb::new(72, 94, 48),
775 warning: Rgb::new(140, 108, 62),
776 error: Rgb::new(143, 57, 85),
777 diff_add: Rgb::new(72, 94, 48),
778 diff_del: Rgb::new(143, 57, 85),
779 diff_context: Rgb::new(132, 140, 176),
780 diff_hunk: Rgb::new(90, 74, 120),
781 graph_colors: [
782 Rgb::new(46, 126, 233),
783 Rgb::new(72, 94, 48),
784 Rgb::new(143, 57, 85),
785 Rgb::new(140, 108, 62),
786 Rgb::new(90, 74, 120),
787 Rgb::new(166, 77, 121),
788 Rgb::new(15, 130, 130),
789 Rgb::new(180, 90, 50),
790 ],
791 }
792}
793
794pub fn kanagawa_wave() -> AppTheme {
795 AppTheme {
796 is_dark: true,
797 background: Rgb::new(31, 31, 40),
798 surface: Rgb::new(42, 42, 55),
799 border: Rgb::new(84, 84, 88),
800 selection: Rgb::new(42, 42, 55),
801 text_primary: Rgb::new(220, 215, 186),
802 text_secondary: Rgb::new(126, 156, 216),
803 text_muted: Rgb::new(114, 113, 105),
804 accent: Rgb::new(126, 156, 216),
805 success: Rgb::new(118, 148, 106),
806 warning: Rgb::new(220, 165, 97),
807 error: Rgb::new(195, 64, 67),
808 diff_add: Rgb::new(118, 148, 106),
809 diff_del: Rgb::new(195, 64, 67),
810 diff_context: Rgb::new(114, 113, 105),
811 diff_hunk: Rgb::new(210, 126, 153),
812 graph_colors: [
813 Rgb::new(126, 156, 216),
814 Rgb::new(118, 148, 106),
815 Rgb::new(195, 64, 67),
816 Rgb::new(220, 165, 97),
817 Rgb::new(210, 126, 153),
818 Rgb::new(160, 140, 200),
819 Rgb::new(106, 149, 137),
820 Rgb::new(228, 104, 118),
821 ],
822 }
823}
824
825pub fn kanagawa_dragon() -> AppTheme {
826 AppTheme {
827 is_dark: true,
828 background: Rgb::new(24, 21, 21),
829 surface: Rgb::new(40, 39, 39),
830 border: Rgb::new(80, 80, 78),
831 selection: Rgb::new(40, 39, 39),
832 text_primary: Rgb::new(197, 201, 197),
833 text_secondary: Rgb::new(139, 164, 176),
834 text_muted: Rgb::new(166, 166, 156),
835 accent: Rgb::new(139, 164, 176),
836 success: Rgb::new(135, 169, 135),
837 warning: Rgb::new(200, 170, 109),
838 error: Rgb::new(195, 64, 67),
839 diff_add: Rgb::new(135, 169, 135),
840 diff_del: Rgb::new(195, 64, 67),
841 diff_context: Rgb::new(166, 166, 156),
842 diff_hunk: Rgb::new(210, 126, 153),
843 graph_colors: [
844 Rgb::new(139, 164, 176),
845 Rgb::new(135, 169, 135),
846 Rgb::new(195, 64, 67),
847 Rgb::new(200, 170, 109),
848 Rgb::new(210, 126, 153),
849 Rgb::new(160, 140, 200),
850 Rgb::new(106, 149, 137),
851 Rgb::new(228, 104, 118),
852 ],
853 }
854}
855
856pub fn kanagawa_lotus() -> AppTheme {
857 AppTheme {
858 is_dark: false,
859 background: Rgb::new(245, 240, 215),
860 surface: Rgb::new(231, 219, 160),
861 border: Rgb::new(196, 178, 138),
862 selection: Rgb::new(231, 219, 160),
863 text_primary: Rgb::new(84, 84, 100),
864 text_secondary: Rgb::new(77, 105, 155),
865 text_muted: Rgb::new(196, 178, 138),
866 accent: Rgb::new(77, 105, 155),
867 success: Rgb::new(111, 137, 78),
868 warning: Rgb::new(119, 113, 63),
869 error: Rgb::new(195, 64, 67),
870 diff_add: Rgb::new(111, 137, 78),
871 diff_del: Rgb::new(195, 64, 67),
872 diff_context: Rgb::new(196, 178, 138),
873 diff_hunk: Rgb::new(160, 154, 190),
874 graph_colors: [
875 Rgb::new(77, 105, 155),
876 Rgb::new(111, 137, 78),
877 Rgb::new(195, 64, 67),
878 Rgb::new(119, 113, 63),
879 Rgb::new(160, 154, 190),
880 Rgb::new(155, 80, 117),
881 Rgb::new(75, 130, 120),
882 Rgb::new(180, 100, 55),
883 ],
884 }
885}
886
887pub fn moonfly() -> AppTheme {
888 AppTheme {
889 is_dark: true,
890 background: Rgb::new(8, 8, 8),
891 surface: Rgb::new(23, 23, 23),
892 border: Rgb::new(50, 50, 50),
893 selection: Rgb::new(23, 50, 80),
894 text_primary: Rgb::new(189, 189, 189),
895 text_secondary: Rgb::new(128, 160, 255),
896 text_muted: Rgb::new(99, 99, 99),
897 accent: Rgb::new(174, 129, 255),
898 success: Rgb::new(130, 170, 60),
899 warning: Rgb::new(230, 170, 50),
900 error: Rgb::new(255, 83, 112),
901 diff_add: Rgb::new(130, 170, 60),
902 diff_del: Rgb::new(255, 83, 112),
903 diff_context: Rgb::new(99, 99, 99),
904 diff_hunk: Rgb::new(128, 160, 255),
905 graph_colors: [
906 Rgb::new(174, 129, 255),
907 Rgb::new(130, 170, 60),
908 Rgb::new(255, 83, 112),
909 Rgb::new(230, 170, 50),
910 Rgb::new(128, 160, 255),
911 Rgb::new(255, 100, 180),
912 Rgb::new(80, 200, 180),
913 Rgb::new(255, 160, 80),
914 ],
915 }
916}
917
918pub fn nightfly() -> AppTheme {
919 AppTheme {
920 is_dark: true,
921 background: Rgb::new(1, 13, 32),
922 surface: Rgb::new(5, 22, 50),
923 border: Rgb::new(30, 50, 80),
924 selection: Rgb::new(10, 40, 80),
925 text_primary: Rgb::new(195, 204, 219),
926 text_secondary: Rgb::new(130, 170, 255),
927 text_muted: Rgb::new(99, 117, 150),
928 accent: Rgb::new(130, 170, 255),
929 success: Rgb::new(161, 217, 147),
930 warning: Rgb::new(236, 196, 100),
931 error: Rgb::new(252, 57, 49),
932 diff_add: Rgb::new(161, 217, 147),
933 diff_del: Rgb::new(252, 57, 49),
934 diff_context: Rgb::new(99, 117, 150),
935 diff_hunk: Rgb::new(174, 129, 255),
936 graph_colors: [
937 Rgb::new(130, 170, 255),
938 Rgb::new(161, 217, 147),
939 Rgb::new(252, 57, 49),
940 Rgb::new(236, 196, 100),
941 Rgb::new(174, 129, 255),
942 Rgb::new(255, 100, 180),
943 Rgb::new(33, 200, 170),
944 Rgb::new(255, 160, 90),
945 ],
946 }
947}
948
949pub fn oxocarbon() -> AppTheme {
950 AppTheme {
951 is_dark: true,
952 background: Rgb::new(22, 22, 22),
953 surface: Rgb::new(38, 38, 38),
954 border: Rgb::new(57, 57, 57),
955 selection: Rgb::new(38, 38, 38),
956 text_primary: Rgb::new(240, 240, 240),
957 text_secondary: Rgb::new(78, 154, 232),
958 text_muted: Rgb::new(82, 82, 82),
959 accent: Rgb::new(78, 154, 232),
960 success: Rgb::new(66, 190, 101),
961 warning: Rgb::new(190, 149, 255),
962 error: Rgb::new(238, 83, 120),
963 diff_add: Rgb::new(66, 190, 101),
964 diff_del: Rgb::new(238, 83, 120),
965 diff_context: Rgb::new(82, 82, 82),
966 diff_hunk: Rgb::new(51, 177, 255),
967 graph_colors: [
968 Rgb::new(78, 154, 232),
969 Rgb::new(66, 190, 101),
970 Rgb::new(238, 83, 120),
971 Rgb::new(190, 149, 255),
972 Rgb::new(51, 177, 255),
973 Rgb::new(255, 104, 159),
974 Rgb::new(8, 189, 186),
975 Rgb::new(255, 164, 90),
976 ],
977 }
978}
979
980#[cfg(test)]
983mod tests {
984 use super::*;
985
986 #[test]
987 fn all_themes_resolve() {
988 for i in 0..THEME_COUNT {
989 let t = theme_by_index(i);
990 assert!(
992 t.text_primary.r > 0 || t.text_primary.g > 0 || t.text_primary.b > 0,
993 "theme index {i} has zero text_primary"
994 );
995 }
996 }
997
998 #[test]
999 fn theme_count_matches_names() {
1000 assert_eq!(THEME_NAMES.len(), THEME_COUNT);
1001 }
1002
1003 #[test]
1004 fn index_by_name_round_trips() {
1005 for (i, name) in THEME_NAMES.iter().enumerate() {
1006 assert_eq!(
1007 theme_index_by_name(name),
1008 i,
1009 "round-trip failed for '{name}'"
1010 );
1011 }
1012 }
1013
1014 #[test]
1015 fn unknown_name_returns_zero() {
1016 assert_eq!(theme_index_by_name("nonexistent"), 0);
1017 }
1018
1019 #[test]
1020 fn out_of_range_returns_default() {
1021 let d = default();
1022 let oob = theme_by_index(999);
1023 assert_eq!(d.background, oob.background);
1024 assert_eq!(d.accent, oob.accent);
1025 }
1026
1027 #[test]
1028 fn graph_colors_populated_for_all_themes() {
1029 for i in 0..THEME_COUNT {
1030 let t = theme_by_index(i);
1031 assert_eq!(
1033 t.graph_colors.len(),
1034 8,
1035 "theme index {i} does not have 8 graph_colors"
1036 );
1037 let first = t.graph_colors[0];
1039 let all_same = t.graph_colors.iter().all(|c| *c == first);
1040 assert!(
1041 !all_same,
1042 "theme index {i} has all identical graph lane colours"
1043 );
1044 }
1045 }
1046
1047 #[test]
1048 fn graph_colors_channels_nonzero() {
1049 for i in 0..THEME_COUNT {
1050 let t = theme_by_index(i);
1051 for (lane, c) in t.graph_colors.iter().enumerate() {
1052 assert!(
1055 c.r > 0 || c.g > 0 || c.b > 0,
1056 "theme {i} graph_colors[{lane}] is pure black"
1057 );
1058 }
1059 }
1060 }
1061}