1use ratatui::style::Color;
2
3#[derive(Clone)]
4pub struct Theme {
5 pub name: String,
6 pub background: Option<Color>,
8 pub title_try: Color,
10 pub title_rs: Color,
11 pub search_title: Color,
13 pub search_border: Color,
14 pub folder_title: Color,
16 pub folder_border: Color,
17 pub disk_title: Color,
19 pub disk_border: Color,
20 pub preview_title: Color,
22 pub preview_border: Color,
23 pub legends_title: Color,
25 pub legends_border: Color,
26 pub list_date: Color,
28 pub list_highlight_bg: Color,
29 pub list_highlight_fg: Color,
30 pub list_match_fg: Color,
31 pub list_selected_fg: Color,
32 pub helpers_colors: Color,
34 pub status_message: Color,
35 pub popup_bg: Color,
37 pub popup_text: Color,
38 pub icon_rust: Color,
40 pub icon_maven: Color,
41 pub icon_flutter: Color,
42 pub icon_go: Color,
43 pub icon_python: Color,
44 pub icon_mise: Color,
45 pub icon_worktree: Color,
46 pub icon_worktree_lock: Color,
47 pub icon_gitmodules: Color,
48 pub icon_git: Color,
49 pub icon_folder: Color,
50 pub icon_file: Color,
51}
52
53impl Default for Theme {
54 fn default() -> Self {
55 Self::default_theme()
56 }
57}
58
59struct Palette {
74 accent1: Color,
75 accent2: Color,
76 warm: Color,
77 cool: Color,
78 green: Color,
79 yellow: Color,
80 purple: Color,
81 overlay: Color,
82 subtext: Color,
83 surface: Color,
84 text: Color,
85 base: Color,
86}
87
88impl Theme {
89 fn from_palette(name: &str, background: Option<Color>, p: Palette) -> Self {
91 Self {
92 name: name.to_string(),
93 background,
94 title_try: p.accent1,
95 title_rs: p.accent2,
96 search_title: p.warm,
97 search_border: p.overlay,
98 folder_title: p.green,
99 folder_border: p.overlay,
100 disk_title: p.yellow,
101 disk_border: p.overlay,
102 preview_title: p.accent1,
103 preview_border: p.overlay,
104 legends_title: p.purple,
105 legends_border: p.overlay,
106 list_date: p.subtext,
107 list_highlight_bg: p.surface,
108 list_highlight_fg: p.text,
109 list_match_fg: p.warm,
110 list_selected_fg: p.text,
111 helpers_colors: p.overlay,
112 status_message: p.yellow,
113 popup_bg: p.base,
114 popup_text: p.accent2,
115 icon_rust: p.warm,
116 icon_maven: p.accent2,
117 icon_flutter: p.accent1,
118 icon_go: p.cool,
119 icon_python: p.yellow,
120 icon_mise: p.warm,
121 icon_worktree: p.green,
122 icon_worktree_lock: p.subtext,
123 icon_gitmodules: p.purple,
124 icon_git: p.accent2,
125 icon_folder: p.yellow,
126 icon_file: p.subtext,
127 }
128 }
129
130 pub fn default_theme() -> Self {
131 Self {
132 icon_rust: Color::Rgb(230, 100, 50),
134 icon_maven: Color::Rgb(255, 150, 50),
135 icon_flutter: Color::Rgb(2, 123, 222),
136 icon_go: Color::Rgb(0, 173, 216),
137 icon_python: Color::Yellow,
138 icon_mise: Color::Rgb(250, 179, 135),
139 icon_worktree: Color::Rgb(100, 180, 100),
140 icon_worktree_lock: Color::White,
141 icon_gitmodules: Color::Rgb(180, 130, 200),
142 icon_git: Color::Rgb(240, 80, 50),
143 icon_folder: Color::Rgb(249, 226, 175),
144 icon_file: Color::Rgb(166, 173, 200),
145 ..Self::from_palette(
146 "Default",
147 None,
148 Palette {
149 accent1: Color::Rgb(137, 180, 250), accent2: Color::Rgb(243, 139, 168), warm: Color::Rgb(250, 179, 135), cool: Color::Rgb(0, 173, 216), green: Color::Rgb(166, 227, 161), yellow: Color::Rgb(249, 226, 175), purple: Color::Rgb(203, 166, 247), overlay: Color::Rgb(147, 153, 178), subtext: Color::Rgb(166, 173, 200), surface: Color::Rgb(88, 91, 112), text: Color::Rgb(205, 214, 244), base: Color::Rgb(30, 30, 46), },
162 )
163 }
164 }
165
166 pub fn catppuccin_mocha() -> Self {
167 Self::from_palette(
168 "Catppuccin Mocha",
169 Some(Color::Rgb(30, 30, 46)),
170 Palette {
171 accent1: Color::Rgb(137, 180, 250), accent2: Color::Rgb(243, 139, 168), warm: Color::Rgb(250, 179, 135), cool: Color::Rgb(148, 226, 213), green: Color::Rgb(166, 227, 161), yellow: Color::Rgb(249, 226, 175), purple: Color::Rgb(203, 166, 247), overlay: Color::Rgb(147, 153, 178), subtext: Color::Rgb(166, 173, 200), surface: Color::Rgb(88, 91, 112), text: Color::Rgb(205, 214, 244), base: Color::Rgb(30, 30, 46), },
184 )
185 }
186
187 pub fn catppuccin_macchiato() -> Self {
188 Self {
189 title_rs: Color::Rgb(238, 153, 160), ..Self::from_palette(
191 "Catppuccin Macchiato",
192 Some(Color::Rgb(36, 39, 58)),
193 Palette {
194 accent1: Color::Rgb(138, 173, 244), accent2: Color::Rgb(237, 135, 150), warm: Color::Rgb(245, 169, 127), cool: Color::Rgb(139, 213, 202), green: Color::Rgb(166, 218, 149), yellow: Color::Rgb(238, 212, 159), purple: Color::Rgb(198, 160, 246), overlay: Color::Rgb(147, 154, 183), subtext: Color::Rgb(165, 173, 203), surface: Color::Rgb(91, 96, 120), text: Color::Rgb(202, 211, 245), base: Color::Rgb(36, 39, 58), },
207 )
208 }
209 }
210
211 pub fn dracula() -> Self {
212 let cyan = Color::Rgb(139, 233, 253);
213 Self {
214 preview_title: cyan,
215 list_date: cyan,
216 popup_text: Color::Rgb(255, 85, 85), icon_flutter: cyan,
218 icon_go: cyan,
219 icon_file: cyan,
220 icon_maven: Color::Rgb(255, 85, 85), icon_worktree_lock: Color::Rgb(248, 248, 242), ..Self::from_palette(
223 "Dracula",
224 Some(Color::Rgb(40, 42, 54)),
225 Palette {
226 accent1: Color::Rgb(189, 147, 249), accent2: Color::Rgb(255, 121, 198), warm: Color::Rgb(255, 184, 108), cool: Color::Rgb(139, 233, 253), green: Color::Rgb(80, 250, 123), yellow: Color::Rgb(241, 250, 140), purple: Color::Rgb(189, 147, 249), overlay: Color::Rgb(98, 114, 164), subtext: Color::Rgb(139, 233, 253), surface: Color::Rgb(68, 71, 90), text: Color::Rgb(248, 248, 242), base: Color::Rgb(40, 42, 54), },
239 )
240 }
241 }
242
243 pub fn jetbrains_darcula() -> Self {
244 Self {
245 search_title: Color::Rgb(106, 135, 89), list_match_fg: Color::Rgb(106, 135, 89), disk_title: Color::Rgb(204, 120, 50), icon_maven: Color::Rgb(255, 198, 109), icon_worktree: Color::Rgb(106, 135, 89), icon_worktree_lock: Color::Rgb(187, 187, 187), ..Self::from_palette(
252 "JetBrains Darcula",
253 Some(Color::Rgb(43, 43, 43)),
254 Palette {
255 accent1: Color::Rgb(78, 124, 238), accent2: Color::Rgb(204, 120, 50), warm: Color::Rgb(204, 120, 50), cool: Color::Rgb(0, 173, 216), green: Color::Rgb(255, 198, 109), yellow: Color::Rgb(255, 198, 109), purple: Color::Rgb(152, 118, 170), overlay: Color::Rgb(128, 128, 128), subtext: Color::Rgb(128, 128, 128), surface: Color::Rgb(33, 66, 131), text: Color::Rgb(187, 187, 187), base: Color::Rgb(60, 63, 65), },
268 )
269 }
270 }
271
272 pub fn gruvbox_dark() -> Self {
273 Self {
274 title_rs: Color::Rgb(250, 189, 47), search_title: Color::Rgb(184, 187, 38), list_match_fg: Color::Rgb(184, 187, 38), folder_title: Color::Rgb(250, 189, 47), disk_title: Color::Rgb(254, 128, 25), preview_title: Color::Rgb(131, 165, 152), status_message: Color::Rgb(215, 153, 33), icon_flutter: Color::Rgb(131, 165, 152), icon_worktree_lock: Color::Rgb(168, 153, 132), ..Self::from_palette(
284 "Gruvbox Dark",
285 Some(Color::Rgb(40, 40, 40)),
286 Palette {
287 accent1: Color::Rgb(251, 73, 52), accent2: Color::Rgb(251, 73, 52), warm: Color::Rgb(254, 128, 25), cool: Color::Rgb(131, 165, 152), green: Color::Rgb(184, 187, 38), yellow: Color::Rgb(250, 189, 47), purple: Color::Rgb(211, 134, 155), overlay: Color::Rgb(168, 153, 132), subtext: Color::Rgb(146, 131, 116), surface: Color::Rgb(80, 73, 69), text: Color::Rgb(235, 219, 178), base: Color::Rgb(40, 40, 40), },
300 )
301 }
302 }
303
304 pub fn nord() -> Self {
305 Self {
306 search_title: Color::Rgb(163, 190, 140), list_match_fg: Color::Rgb(163, 190, 140), folder_title: Color::Rgb(235, 203, 139), disk_title: Color::Rgb(208, 135, 112), icon_worktree: Color::Rgb(163, 190, 140), ..Self::from_palette(
312 "Nord",
313 Some(Color::Rgb(46, 52, 64)),
314 Palette {
315 accent1: Color::Rgb(136, 192, 208), accent2: Color::Rgb(191, 97, 106), warm: Color::Rgb(208, 135, 112), cool: Color::Rgb(136, 192, 208), green: Color::Rgb(163, 190, 140), yellow: Color::Rgb(235, 203, 139), purple: Color::Rgb(180, 142, 173), overlay: Color::Rgb(76, 86, 106), subtext: Color::Rgb(216, 222, 233), surface: Color::Rgb(67, 76, 94), text: Color::Rgb(236, 239, 244), base: Color::Rgb(46, 52, 64), },
328 )
329 }
330 }
331
332 pub fn tokyo_night() -> Self {
333 let cyan = Color::Rgb(125, 207, 255);
334 Self {
335 search_title: Color::Rgb(158, 206, 106), list_match_fg: Color::Rgb(158, 206, 106), disk_title: Color::Rgb(255, 158, 100), preview_title: cyan,
339 icon_flutter: cyan,
340 icon_go: cyan,
341 icon_worktree: Color::Rgb(158, 206, 106), ..Self::from_palette(
343 "Tokyo Night",
344 Some(Color::Rgb(26, 27, 38)),
345 Palette {
346 accent1: Color::Rgb(122, 162, 247), accent2: Color::Rgb(247, 118, 142), warm: Color::Rgb(255, 158, 100), cool: Color::Rgb(125, 207, 255), green: Color::Rgb(224, 175, 104), yellow: Color::Rgb(224, 175, 104), purple: Color::Rgb(187, 154, 247), overlay: Color::Rgb(86, 95, 137), subtext: Color::Rgb(169, 177, 214), surface: Color::Rgb(65, 72, 104), text: Color::Rgb(192, 202, 245), base: Color::Rgb(26, 27, 38), },
359 )
360 }
361 }
362
363 pub fn one_dark_pro() -> Self {
364 let cyan = Color::Rgb(86, 182, 194);
365 Self {
366 preview_title: cyan,
367 icon_flutter: cyan,
368 icon_go: cyan,
369 ..Self::from_palette(
370 "One Dark Pro",
371 Some(Color::Rgb(40, 44, 52)),
372 Palette {
373 accent1: Color::Rgb(97, 175, 239), accent2: Color::Rgb(224, 108, 117), warm: Color::Rgb(209, 154, 102), cool: Color::Rgb(86, 182, 194), green: Color::Rgb(152, 195, 121), yellow: Color::Rgb(229, 192, 123), purple: Color::Rgb(198, 120, 221), overlay: Color::Rgb(92, 99, 112), subtext: Color::Rgb(171, 178, 191), surface: Color::Rgb(62, 68, 81), text: Color::Rgb(220, 223, 228), base: Color::Rgb(40, 44, 52), },
386 )
387 }
388 }
389
390 pub fn everforest() -> Self {
391 Self::from_palette(
392 "Everforest",
393 Some(Color::Rgb(45, 51, 48)),
394 Palette {
395 accent1: Color::Rgb(127, 187, 179), accent2: Color::Rgb(230, 126, 128), warm: Color::Rgb(230, 152, 117), cool: Color::Rgb(127, 187, 179), green: Color::Rgb(167, 192, 128), yellow: Color::Rgb(219, 188, 127), purple: Color::Rgb(214, 153, 182), overlay: Color::Rgb(127, 132, 120), subtext: Color::Rgb(211, 198, 170), surface: Color::Rgb(80, 88, 77), text: Color::Rgb(211, 198, 170), base: Color::Rgb(45, 51, 48), },
408 )
409 }
410
411 pub fn synthwave_84() -> Self {
412 Self {
413 search_title: Color::Rgb(255, 203, 107), list_match_fg: Color::Rgb(255, 203, 107), legends_title: Color::Rgb(254, 78, 174), popup_text: Color::Rgb(254, 78, 174), icon_rust: Color::Rgb(255, 140, 66), icon_gitmodules: Color::Rgb(254, 78, 174), ..Self::from_palette(
420 "SynthWave '84",
421 Some(Color::Rgb(38, 29, 53)),
422 Palette {
423 accent1: Color::Rgb(54, 244, 244), accent2: Color::Rgb(255, 126, 185), warm: Color::Rgb(255, 140, 66), cool: Color::Rgb(54, 244, 244), green: Color::Rgb(114, 241, 177), yellow: Color::Rgb(255, 203, 107), purple: Color::Rgb(254, 78, 174), overlay: Color::Rgb(129, 91, 164), subtext: Color::Rgb(187, 186, 201), surface: Color::Rgb(57, 43, 75), text: Color::Rgb(255, 255, 255), base: Color::Rgb(38, 29, 53), },
436 )
437 }
438 }
439
440 pub fn oled_true_black() -> Self {
441 Self {
442 helpers_colors: Color::Rgb(100, 100, 100), icon_rust: Color::Rgb(255, 120, 50), icon_mise: Color::Rgb(255, 180, 0), ..Self::from_palette(
446 "OLED True Black",
447 Some(Color::Rgb(0, 0, 0)),
448 Palette {
449 accent1: Color::Rgb(0, 200, 255), accent2: Color::Rgb(255, 80, 100), warm: Color::Rgb(255, 180, 0), cool: Color::Rgb(0, 200, 255), green: Color::Rgb(0, 230, 130), yellow: Color::Rgb(255, 220, 0), purple: Color::Rgb(200, 100, 255), overlay: Color::Rgb(60, 60, 60), subtext: Color::Rgb(180, 180, 180), surface: Color::Rgb(30, 30, 30), text: Color::Rgb(255, 255, 255), base: Color::Rgb(0, 0, 0), },
462 )
463 }
464 }
465
466 pub fn silver_gray() -> Self {
467 Self {
468 preview_title: Color::Rgb(176, 196, 222), icon_rust: Color::Rgb(210, 105, 30), icon_go: Color::Rgb(176, 196, 222), ..Self::from_palette(
472 "Silver Gray",
473 Some(Color::Rgb(47, 47, 47)),
474 Palette {
475 accent1: Color::Rgb(100, 149, 237), accent2: Color::Rgb(205, 92, 92), warm: Color::Rgb(218, 165, 32), cool: Color::Rgb(176, 196, 222), green: Color::Rgb(144, 238, 144), yellow: Color::Rgb(240, 230, 140), purple: Color::Rgb(186, 85, 211), overlay: Color::Rgb(128, 128, 128), subtext: Color::Rgb(192, 192, 192), surface: Color::Rgb(70, 70, 70), text: Color::Rgb(245, 245, 245), base: Color::Rgb(47, 47, 47), },
488 )
489 }
490 }
491
492 pub fn black_and_white() -> Self {
493 Self {
494 icon_mise: Color::Gray,
495 icon_gitmodules: Color::Gray,
496 popup_text: Color::White,
497 list_highlight_bg: Color::White,
498 list_highlight_fg: Color::Gray,
499 list_selected_fg: Color::Black,
500 ..Self::from_palette(
501 "Black & White",
502 Some(Color::Black),
503 Palette {
504 accent1: Color::White,
505 accent2: Color::White,
506 warm: Color::White,
507 cool: Color::White,
508 green: Color::White,
509 yellow: Color::White,
510 purple: Color::White,
511 overlay: Color::Gray,
512 subtext: Color::Gray,
513 surface: Color::White,
514 text: Color::White,
515 base: Color::Black,
516 },
517 )
518 }
519 }
520
521 pub fn matrix() -> Self {
522 let bright = Color::Rgb(0, 255, 65);
523 let dark = Color::Rgb(0, 100, 30);
524 let muted = Color::Rgb(0, 150, 40);
525 let darker = Color::Rgb(0, 200, 50);
526 Self {
527 helpers_colors: Color::Rgb(0, 150, 40), popup_text: Color::Rgb(0, 255, 65), icon_maven: Color::Rgb(0, 220, 55),
530 icon_flutter: Color::Rgb(0, 200, 50), icon_go: Color::Rgb(0, 180, 45),
532 icon_mise: Color::Rgb(0, 150, 40), icon_worktree: darker,
534 icon_worktree_lock: Color::Rgb(0, 120, 35),
535 icon_gitmodules: Color::Rgb(0, 180, 45),
536 icon_folder: Color::Rgb(0, 220, 55),
537 ..Self::from_palette(
538 "Matrix",
539 Some(Color::Rgb(0, 10, 0)),
540 Palette {
541 accent1: bright,
542 accent2: darker,
543 warm: bright,
544 cool: Color::Rgb(0, 180, 45),
545 green: bright,
546 yellow: bright,
547 purple: darker,
548 overlay: dark,
549 subtext: muted,
550 surface: Color::Rgb(0, 80, 25),
551 text: bright,
552 base: Color::Rgb(0, 10, 0),
553 },
554 )
555 }
556 }
557
558 pub fn tron() -> Self {
559 let cyan = Color::Rgb(0, 255, 255);
560 let orange = Color::Rgb(255, 150, 0);
561 let dk_cyan = Color::Rgb(0, 150, 180);
562 Self {
563 search_title: cyan,
564 list_match_fg: cyan,
565 folder_title: cyan,
566 legends_title: Color::Rgb(0, 200, 220),
567 popup_text: cyan,
568 icon_maven: Color::Rgb(255, 100, 0),
569 icon_go: Color::Rgb(0, 220, 230),
570 icon_python: Color::Rgb(255, 200, 0),
571 icon_worktree: cyan,
572 icon_worktree_lock: dk_cyan,
573 icon_gitmodules: Color::Rgb(0, 200, 220),
574 icon_folder: cyan,
575 ..Self::from_palette(
576 "Tron",
577 Some(Color::Rgb(0, 10, 15)),
578 Palette {
579 accent1: cyan,
580 accent2: orange,
581 warm: orange,
582 cool: Color::Rgb(0, 220, 230),
583 green: cyan,
584 yellow: orange,
585 purple: Color::Rgb(0, 200, 220),
586 overlay: dk_cyan,
587 subtext: Color::Rgb(0, 180, 200),
588 surface: Color::Rgb(0, 80, 100),
589 text: cyan,
590 base: Color::Rgb(0, 10, 15),
591 },
592 )
593 }
594 }
595
596 pub fn all() -> Vec<Theme> {
597 vec![
598 Theme::default_theme(),
599 Theme::catppuccin_mocha(),
600 Theme::catppuccin_macchiato(),
601 Theme::dracula(),
602 Theme::jetbrains_darcula(),
603 Theme::gruvbox_dark(),
604 Theme::nord(),
605 Theme::tokyo_night(),
606 Theme::one_dark_pro(),
607 Theme::everforest(),
608 Theme::synthwave_84(),
609 Theme::oled_true_black(),
610 Theme::silver_gray(),
611 Theme::black_and_white(),
612 Theme::matrix(),
613 Theme::tron(),
614 ]
615 }
616}