Skip to main content

sqry_cli/output/
theme.rs

1use clap::ValueEnum;
2use colored::{Color, Colorize};
3
4/// Built-in theme selection.
5#[derive(Clone, Copy, Debug, PartialEq, Eq, ValueEnum)]
6pub enum ThemeName {
7    Default,
8    Dark,
9    Light,
10    None,
11}
12
13/// Simple style descriptor for terminal output.
14#[derive(Clone, Copy, Debug)]
15pub struct Style {
16    pub color: Option<Color>,
17    pub bold: bool,
18    pub dimmed: bool,
19}
20
21impl Style {
22    #[must_use]
23    pub fn new(color: Option<Color>, bold: bool, dimmed: bool) -> Self {
24        Self {
25            color,
26            bold,
27            dimmed,
28        }
29    }
30
31    #[must_use]
32    pub fn apply(self, text: &str, use_color: bool) -> String {
33        if !use_color {
34            return text.to_string();
35        }
36
37        let mut styled = text.normal();
38        if let Some(color) = self.color {
39            styled = styled.color(color);
40        }
41        if self.bold {
42            styled = styled.bold();
43        }
44        if self.dimmed {
45            styled = styled.dimmed();
46        }
47        styled.to_string()
48    }
49}
50
51/// Palette of semantic roles for text output.
52#[derive(Clone, Debug)]
53pub struct Palette {
54    pub path: Style,
55    pub location: Style,
56    pub kind: Style,
57    pub name: Style,
58    pub repo_label: Style,
59    pub repo_name: Style,
60    pub dimmed: Style,
61}
62
63impl Palette {
64    #[must_use]
65    pub fn built_in(theme: ThemeName) -> Self {
66        match theme {
67            ThemeName::Default => Self {
68                path: Style::new(Some(Color::Green), false, false),
69                location: Style::new(Some(Color::Blue), false, false),
70                kind: Style::new(Some(Color::Yellow), false, false),
71                name: Style::new(None, true, false),
72                repo_label: Style::new(Some(Color::Magenta), false, false),
73                repo_name: Style::new(None, true, false),
74                dimmed: Style::new(None, false, true),
75            },
76            ThemeName::Dark => Self {
77                path: Style::new(Some(Color::BrightGreen), false, false),
78                location: Style::new(Some(Color::BrightBlue), false, false),
79                kind: Style::new(Some(Color::BrightYellow), false, false),
80                name: Style::new(Some(Color::White), true, false),
81                repo_label: Style::new(Some(Color::BrightMagenta), false, false),
82                repo_name: Style::new(Some(Color::White), true, false),
83                dimmed: Style::new(Some(Color::White), false, true),
84            },
85            ThemeName::Light => Self {
86                path: Style::new(Some(Color::Cyan), false, false),
87                location: Style::new(Some(Color::Blue), false, false),
88                kind: Style::new(Some(Color::Magenta), false, false),
89                name: Style::new(Some(Color::Black), true, false),
90                repo_label: Style::new(Some(Color::Magenta), false, false),
91                repo_name: Style::new(Some(Color::Black), true, false),
92                dimmed: Style::new(Some(Color::Black), false, true),
93            },
94            ThemeName::None => Self {
95                path: Style::new(None, false, false),
96                location: Style::new(None, false, false),
97                kind: Style::new(None, false, false),
98                name: Style::new(None, false, false),
99                repo_label: Style::new(None, false, false),
100                repo_name: Style::new(None, false, false),
101                dimmed: Style::new(None, false, true),
102            },
103        }
104    }
105}