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