1use gpui::{HighlightStyle, Hsla};
2
3use crate::{
4 blue, cyan, gold, indigo, iris, jade, lime, mint, neutral, orange, plum, purple, red, sky,
5 tomato, yellow,
6};
7
8#[derive(Clone, Default)]
9pub struct SyntaxTheme {
10 pub highlights: Vec<(String, HighlightStyle)>,
11 // todo!("Remove this in favor of StatusColor.hint")
12 // If this should be overridable we should move it to ThemeColors
13 pub inlay_style: HighlightStyle,
14 // todo!("Remove this in favor of StatusColor.prediction")
15 // If this should be overridable we should move it to ThemeColors
16 pub suggestion_style: HighlightStyle,
17}
18
19impl SyntaxTheme {
20 pub fn light() -> Self {
21 Self {
22 highlights: vec![
23 ("attribute".into(), cyan().light().step_11().into()),
24 ("boolean".into(), tomato().light().step_11().into()),
25 ("comment".into(), neutral().light().step_11().into()),
26 ("comment.doc".into(), iris().light().step_12().into()),
27 ("constant".into(), red().light().step_9().into()),
28 ("constructor".into(), red().light().step_9().into()),
29 ("embedded".into(), red().light().step_9().into()),
30 ("emphasis".into(), red().light().step_9().into()),
31 ("emphasis.strong".into(), red().light().step_9().into()),
32 ("enum".into(), red().light().step_9().into()),
33 ("function".into(), red().light().step_9().into()),
34 ("hint".into(), red().light().step_9().into()),
35 ("keyword".into(), orange().light().step_11().into()),
36 ("label".into(), red().light().step_9().into()),
37 ("link_text".into(), red().light().step_9().into()),
38 ("link_uri".into(), red().light().step_9().into()),
39 ("number".into(), red().light().step_9().into()),
40 ("operator".into(), red().light().step_9().into()),
41 ("predictive".into(), red().light().step_9().into()),
42 ("preproc".into(), red().light().step_9().into()),
43 ("primary".into(), red().light().step_9().into()),
44 ("property".into(), red().light().step_9().into()),
45 ("punctuation".into(), neutral().light().step_11().into()),
46 (
47 "punctuation.bracket".into(),
48 neutral().light().step_11().into(),
49 ),
50 (
51 "punctuation.delimiter".into(),
52 neutral().light().step_11().into(),
53 ),
54 (
55 "punctuation.list_marker".into(),
56 blue().light().step_11().into(),
57 ),
58 ("punctuation.special".into(), red().light().step_9().into()),
59 ("string".into(), jade().light().step_11().into()),
60 ("string.escape".into(), red().light().step_9().into()),
61 ("string.regex".into(), tomato().light().step_11().into()),
62 ("string.special".into(), red().light().step_9().into()),
63 (
64 "string.special.symbol".into(),
65 red().light().step_9().into(),
66 ),
67 ("tag".into(), red().light().step_9().into()),
68 ("text.literal".into(), red().light().step_9().into()),
69 ("title".into(), red().light().step_9().into()),
70 ("type".into(), red().light().step_9().into()),
71 ("variable".into(), red().light().step_9().into()),
72 ("variable.special".into(), red().light().step_9().into()),
73 ("variant".into(), red().light().step_9().into()),
74 ],
75 inlay_style: tomato().light().step_1().into(), // todo!("nate: use a proper style")
76 suggestion_style: orange().light().step_1().into(), // todo!("nate: use proper style")
77 }
78 }
79
80 pub fn dark() -> Self {
81 Self {
82 highlights: vec![
83 ("attribute".into(), tomato().dark().step_11().into()),
84 ("boolean".into(), tomato().dark().step_11().into()),
85 ("comment".into(), neutral().dark().step_11().into()),
86 ("comment.doc".into(), iris().dark().step_12().into()),
87 ("constant".into(), orange().dark().step_11().into()),
88 ("constructor".into(), gold().dark().step_11().into()),
89 ("embedded".into(), red().dark().step_11().into()),
90 ("emphasis".into(), red().dark().step_11().into()),
91 ("emphasis.strong".into(), red().dark().step_11().into()),
92 ("enum".into(), yellow().dark().step_11().into()),
93 ("function".into(), blue().dark().step_11().into()),
94 ("hint".into(), indigo().dark().step_11().into()),
95 ("keyword".into(), plum().dark().step_11().into()),
96 ("label".into(), red().dark().step_11().into()),
97 ("link_text".into(), red().dark().step_11().into()),
98 ("link_uri".into(), red().dark().step_11().into()),
99 ("number".into(), red().dark().step_11().into()),
100 ("operator".into(), red().dark().step_11().into()),
101 ("predictive".into(), red().dark().step_11().into()),
102 ("preproc".into(), red().dark().step_11().into()),
103 ("primary".into(), red().dark().step_11().into()),
104 ("property".into(), red().dark().step_11().into()),
105 ("punctuation".into(), neutral().dark().step_11().into()),
106 (
107 "punctuation.bracket".into(),
108 neutral().dark().step_11().into(),
109 ),
110 (
111 "punctuation.delimiter".into(),
112 neutral().dark().step_11().into(),
113 ),
114 (
115 "punctuation.list_marker".into(),
116 blue().dark().step_11().into(),
117 ),
118 ("punctuation.special".into(), red().dark().step_11().into()),
119 ("string".into(), lime().dark().step_11().into()),
120 ("string.escape".into(), orange().dark().step_11().into()),
121 ("string.regex".into(), tomato().dark().step_11().into()),
122 ("string.special".into(), red().dark().step_11().into()),
123 (
124 "string.special.symbol".into(),
125 red().dark().step_11().into(),
126 ),
127 ("tag".into(), red().dark().step_11().into()),
128 ("text.literal".into(), purple().dark().step_11().into()),
129 ("title".into(), sky().dark().step_11().into()),
130 ("type".into(), mint().dark().step_11().into()),
131 ("variable".into(), red().dark().step_11().into()),
132 ("variable.special".into(), red().dark().step_11().into()),
133 ("variant".into(), red().dark().step_11().into()),
134 ],
135 inlay_style: neutral().dark().step_11().into(), // todo!("nate: use a proper style")
136 suggestion_style: orange().dark().step_11().into(), // todo!("nate: use a proper style")
137 }
138 }
139
140 // TOOD: Get this working with `#[cfg(test)]`. Why isn't it?
141 pub fn new_test(colors: impl IntoIterator<Item = (&'static str, Hsla)>) -> Self {
142 SyntaxTheme {
143 highlights: colors
144 .into_iter()
145 .map(|(key, color)| {
146 (
147 key.to_owned(),
148 HighlightStyle {
149 color: Some(color),
150 ..Default::default()
151 },
152 )
153 })
154 .collect(),
155 inlay_style: HighlightStyle::default(),
156 suggestion_style: HighlightStyle::default(),
157 }
158 }
159
160 pub fn get(&self, name: &str) -> HighlightStyle {
161 self.highlights
162 .iter()
163 .find_map(|entry| if entry.0 == name { Some(entry.1) } else { None })
164 .unwrap_or_default()
165 }
166
167 pub fn color(&self, name: &str) -> Hsla {
168 self.get(name).color.unwrap_or_default()
169 }
170}