Skip to main content

tsu_editor/theme/
mod.rs

1use crate::color::Color;
2
3mod vscode;
4
5use serde::{Deserialize, Serialize};
6pub use vscode::parse_vscode_theme;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
9pub struct Theme {
10    #[allow(dead_code)]
11    pub name: String,
12    pub style: Style,
13    pub gutter_style: Style,
14    pub status_line_style: StatusLineStyle,
15    pub token_styles: Vec<TokenStyle>,
16    pub selection_style: Option<Style>,
17}
18
19impl Theme {
20    #[must_use]
21    pub fn get_style(&self, scope: &str) -> Option<Style> {
22        self.token_styles.iter().find_map(|token_style| {
23            if token_style.scope.contains(&scope.to_string()) {
24                Some(token_style.style.clone())
25            } else {
26                None
27            }
28        })
29    }
30
31    #[allow(dead_code)]
32    #[must_use]
33    pub fn get_selection_background(&self) -> Color {
34        self.selection_style
35            .as_ref()
36            .and_then(|s| s.background)
37            .unwrap_or(Color::Rgb {
38                r: 255,
39                g: 255,
40                b: 255,
41            })
42    }
43}
44
45impl Default for Theme {
46    fn default() -> Self {
47        Self {
48            name: "default".to_string(),
49            style: Style {
50                foreground: Some(Color::Rgb {
51                    r: 255,
52                    g: 255,
53                    b: 255,
54                }),
55                background: Some(Color::Rgb { r: 0, g: 0, b: 0 }),
56                bold: false,
57                italic: false,
58            },
59            gutter_style: Style::default(),
60            status_line_style: StatusLineStyle::default(),
61            token_styles: vec![],
62            selection_style: None,
63        }
64    }
65}
66
67#[derive(Debug, Clone, Serialize, Deserialize)]
68pub struct TokenStyle {
69    pub name: Option<String>,
70    pub scope: Vec<String>,
71    pub style: Style,
72}
73
74#[derive(Debug, Default, Clone, Serialize, Deserialize)]
75pub struct StatusLineStyle {
76    pub outer_style: Style,
77    pub outer_chars: [char; 4],
78    pub inner_style: Style,
79}
80
81#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize)]
82pub struct Style {
83    pub foreground: Option<Color>,
84    pub background: Option<Color>,
85    pub bold: bool,
86    pub italic: bool,
87}
88
89impl Style {
90    #[allow(dead_code)]
91    #[must_use]
92    pub fn fallback_background(&self, fallback_background: &Style) -> Style {
93        let background = self
94            .background
95            .or(fallback_background.background)
96            .or(Some(Color::Rgb { r: 0, g: 0, b: 0 }));
97        self.with_background(background)
98    }
99
100    #[allow(dead_code)]
101    #[must_use]
102    pub fn with_background(&self, background: Option<Color>) -> Style {
103        Style {
104            background,
105            ..(*self)
106        }
107    }
108
109    #[allow(dead_code)]
110    #[must_use]
111    pub fn inverted(&self) -> Style {
112        Style {
113            foreground: self.background,
114            background: self.foreground,
115            bold: self.bold,
116            italic: self.italic,
117        }
118    }
119}