syntax.rs

  1// Create ThemeSyntaxRefinement
  2// Map tokenColors style to HighlightStyle (fontStyle, foreground, background)
  3// Take in the scopes from the tokenColors and try to match each to our HighlightStyles
  4
  5use anyhow::Result;
  6use indexmap::IndexMap;
  7use serde::Deserialize;
  8use theme::UserHighlightStyle;
  9
 10use crate::util::Traverse;
 11use crate::vscode::{try_parse_color, try_parse_font_style, try_parse_font_weight};
 12
 13#[derive(Debug, Deserialize)]
 14#[serde(untagged)]
 15pub enum VsCodeTokenScope {
 16    One(String),
 17    Many(Vec<String>),
 18}
 19
 20#[derive(Debug, Deserialize)]
 21pub struct VsCodeTokenColor {
 22    pub scope: Option<VsCodeTokenScope>,
 23    pub settings: VsCodeTokenColorSettings,
 24}
 25
 26#[derive(Debug, Deserialize)]
 27pub struct VsCodeTokenColorSettings {
 28    pub foreground: Option<String>,
 29    pub background: Option<String>,
 30    #[serde(rename = "fontStyle")]
 31    pub font_style: Option<String>,
 32}
 33
 34impl VsCodeTokenColor {
 35    pub fn highlight_styles(&self) -> Result<IndexMap<String, UserHighlightStyle>> {
 36        let mut highlight_styles = IndexMap::new();
 37
 38        let scope = match self.scope {
 39            Some(VsCodeTokenScope::One(ref scope)) => vec![scope.clone()],
 40            Some(VsCodeTokenScope::Many(ref scopes)) => scopes.clone(),
 41            None => return Ok(IndexMap::new()),
 42        };
 43
 44        for scope in &scope {
 45            let Some(syntax_token) = Self::to_zed_token(&scope) else {
 46                continue;
 47            };
 48
 49            let highlight_style = UserHighlightStyle {
 50                color: self
 51                    .settings
 52                    .foreground
 53                    .as_ref()
 54                    .traverse(|color| try_parse_color(&color))?,
 55                font_style: self
 56                    .settings
 57                    .font_style
 58                    .as_ref()
 59                    .and_then(|style| try_parse_font_style(&style)),
 60                font_weight: self
 61                    .settings
 62                    .font_style
 63                    .as_ref()
 64                    .and_then(|style| try_parse_font_weight(&style)),
 65            };
 66
 67            if highlight_style.is_empty() {
 68                continue;
 69            }
 70
 71            highlight_styles.insert(syntax_token, highlight_style);
 72        }
 73
 74        Ok(highlight_styles)
 75    }
 76
 77    fn to_zed_token(scope: &str) -> Option<String> {
 78        match scope {
 79            "attribute" => Some("attribute".to_string()),
 80            "boolean" => Some("boolean".to_string()),
 81            "comment" => Some("comment".to_string()),
 82            "comment.doc" => Some("comment.doc".to_string()),
 83            "punctuation"
 84            | "punctuation.accessor"
 85            | "punctuation.definition.array.begin.json"
 86            | "punctuation.definition.array.end.json"
 87            | "punctuation.definition.dictionary.begin.json"
 88            | "punctuation.definition.dictionary.end.json"
 89            | "punctuation.definition.markdown"
 90            | "punctuation.definition.tag"
 91            | "punctuation.definition.tag.begin"
 92            | "punctuation.definition.tag.end"
 93            | "punctuation.definition.template-expression"
 94            | "punctuation.definition.variable"
 95            | "punctuation.section"
 96            | "punctuation.section.embedded"
 97            | "punctuation.section.embedded.begin"
 98            | "punctuation.section.embedded.end"
 99            | "punctuation.separator"
100            | "punctuation.separator.array.json"
101            | "punctuation.separator.dictionary.key-value.json"
102            | "punctuation.separator.dictionary.pair.json" => Some("punctuation".to_string()),
103
104            // ---
105            "constant" | "character" | "language" | "language.python" | "numeric" | "other"
106            | "other.symbol" => Some("something".to_string()),
107
108            "entity"
109            | "name"
110            | "name.class"
111            | "name.filename.find-in-files"
112            | "name.function"
113            | "name.function.python"
114            | "name.import"
115            | "name.package"
116            | "name.tag"
117            | "name.type"
118            | "name.type.class.python"
119            | "other.attribute-name"
120            | "other.inherited-class" => Some("something".to_string()),
121
122            "markup" | "bold" | "changed" | "deleted" | "heading" | "heading.setext"
123            | "inline.raw" | "italic" | "list" | "quote" | "raw" | "raw.inline" | "strike"
124            | "table" | "underline.link" => Some("something".to_string()),
125
126            "source" => Some("something".to_string()),
127            "storage" => Some("something".to_string()),
128            "string" => Some("something".to_string()),
129            "support" => Some("something".to_string()),
130            "text" => Some("something".to_string()),
131            "token" => Some("something".to_string()),
132            "variable" => Some("something".to_string()),
133            _ => None,
134        }
135    }
136}
137
138// "comment" => ""
139// "constant.character" => ""
140// "constant.language" => ""
141// "constant.language.python" => ""
142// "constant.numeric" => ""
143// "constant.numeric.line-number.find-in-files - match" => ""
144// "constant.numeric.line-number.match" => ""
145// "constant.other" => ""
146// "constant.other.symbol" => ""
147// "entity.name" => ""
148// "entity.name.class" => ""
149// "entity.name.filename.find-in-files" => ""
150// "entity.name.function" => ""
151// "entity.name.function.python" => ""
152// "entity.name.import" => ""
153// "entity.name.package" => ""
154// "entity.name.tag" => ""
155// "entity.name.type" => ""
156// "entity.name.type.class.python" => ""
157// "entity.other.attribute-name" => ""
158// "entity.other.inherited-class" => ""
159// "invalid" => ""
160// "keyword" => ""
161// "keyword.control.from" => ""
162// "keyword.control.import" => ""
163// "keyword.operator" => ""
164// "keyword.other.new" => ""
165// "markup.bold markup.italic" => ""
166// "markup.bold" => ""
167// "markup.changed" => ""
168// "markup.deleted" => ""
169// "markup.heading entity.name" => ""
170// "markup.heading" => ""
171// "markup.heading.setext" => ""
172// "markup.inline.raw" => ""
173// "markup.inserted" => ""
174// "markup.inserted" => ""
175// "markup.italic markup.bold" => ""
176// "markup.italic" => ""
177// "markup.list punctuation.definition.list.begin" => ""
178// "markup.list" => ""
179// "markup.quote" => ""
180// "markup.raw" => ""
181// "markup.raw.inline" => ""
182// "markup.strike" => ""
183// "markup.table" => ""
184// "markup.underline.link" => ""
185// "message.error" => ""
186// "meta.decorator punctuation.decorator" => ""
187// "meta.decorator variable.other" => ""
188// "meta.diff" => ""
189// "meta.diff.header" => ""
190// "meta.embedded" => ""
191// "meta.function-call" => ""
192// "meta.function-call.generic" => ""
193// "meta.import" => ""
194// "meta.parameter" => ""
195// "meta.preprocessor" => ""
196// "meta.separator" => ""
197// "meta.tag.sgml" => ""
198// "punctuation.accessor" => ""
199// "punctuation.definition.array.begin.json" => ""
200// "punctuation.definition.array.end.json" => ""
201// "punctuation.definition.dictionary.begin.json" => ""
202// "punctuation.definition.dictionary.end.json" => ""
203// "punctuation.definition.markdown" => ""
204// "punctuation.definition.tag" => ""
205// "punctuation.definition.tag.begin" => ""
206// "punctuation.definition.tag.end" => ""
207// "punctuation.definition.template-expression" => ""
208// "punctuation.definition.variable" => ""
209// "punctuation.section" => ""
210// "punctuation.section.embedded" => ""
211// "punctuation.section.embedded.begin" => ""
212// "punctuation.section.embedded.end" => ""
213// "punctuation.separator" => ""
214// "punctuation.separator.array.json" => ""
215// "punctuation.separator.dictionary.key-value.json" => ""
216// "punctuation.separator.dictionary.pair.json" => ""
217// "punctuation.terminator" => ""
218// "source.c storage.type" => ""
219// "source.css entity.name.tag" => ""
220// "source.css support.type" => ""
221// "source.go storage.type" => ""
222// "source.groovy.embedded" => ""
223// "source.haskell storage.type" => ""
224// "source.java storage.type" => ""
225// "source.java storage.type.primitive" => ""
226// "source.less entity.name.tag" => ""
227// "source.less support.type" => ""
228// "source.python" => ""
229// "source.ruby variable.other.readwrite" => ""
230// "source.sass entity.name.tag" => ""
231// "source.sass support.type" => ""
232// "source.scss entity.name.tag" => ""
233// "source.scss support.type" => ""
234// "source.stylus entity.name.tag" => ""
235// "source.stylus support.type" => ""
236// "source.ts" => ""
237// "storage" => ""
238// "storage.modifier" => ""
239// "storage.modifier.async" => ""
240// "storage.modifier.tsx" => ""
241// "storage.type.annotation" => ""
242// "storage.type.function" => ""
243// "string" => ""
244// "string.other.link" => ""
245// "string.regexp" => ""
246// "support.class" => ""
247// "support.class.component" => ""
248// "support.constant" => ""
249// "support.function" => ""
250// "support.function.construct" => ""
251// "support.function.go" => ""
252// "support.macro" => ""
253// "support.other.variable" => ""
254// "support.type" => ""
255// "support.type.exception" => ""
256// "support.type.primitive" => ""
257// "support.type.property-name" => ""
258// "support.type.python" => ""
259// "text.html.markdown markup.inline.raw" => ""
260// "text.html.markdown meta.dummy.line-break" => ""
261// "token.debug-token" => ""
262// "token.error-token" => ""
263// "token.info-token" => ""
264// "token.warn-token" => ""
265// "variable" => ""
266// "variable.annotation" => ""
267// "variable.function" => ""
268// "variable.language" => ""
269// "variable.member" => ""
270// "variable.object.property" => ""
271// "variable.other" => ""
272// "variable.parameter" => ""
273// "variable.parameter.function-call" => ""