Cargo.lock ๐
@@ -9331,6 +9331,7 @@ dependencies = [
"async-trait",
"clock",
"collections",
+ "criterion",
"ctor",
"diffy",
"ec4rs",
Finn Evers , Piotr Osiewicz , and Gaauwe Rombouts created
This PR refactors the highlight map capture name resolution to be faster
and more predictable. Speficically,
- it changes the capture name matching to explicit prefix matching
(e.g., `function.call.whatever.jsx` will now be matched by only
`function`, `function.call`, `function.call.whatever` and
`function.call.whatever.jsx`). This matches the behavior VSCode has
- resolving highlights is now much more efficient, as we now look up
captures in a BTreeMap as opposed to searching in a Vector for these.
This substantially improves the performance for resolving capture names
against themes. With the benchmark added here for creating the
HighlightMap, we see quite some improvements:
```
Running benches/highlight_map.rs (target/release/deps/highlight_map-f99da68650aac85b)
HighlightMap::new/small_captures/small_theme
time: [161.90 ns 162.70 ns 163.55 ns]
change: [-39.027% -38.352% -37.742%] (p = 0.00 < 0.05)
Performance has improved.
Found 3 outliers among 100 measurements (3.00%)
3 (3.00%) high mild
HighlightMap::new/small_captures/large_theme
time: [231.37 ns 233.02 ns 234.70 ns]
change: [-91.570% -91.516% -91.464%] (p = 0.00 < 0.05)
Performance has improved.
HighlightMap::new/large_captures/small_theme
time: [991.82 ns 994.94 ns 998.50 ns]
change: [-50.670% -50.443% -50.220%] (p = 0.00 < 0.05)
Performance has improved.
Found 5 outliers among 100 measurements (5.00%)
5 (5.00%) high mild
HighlightMap::new/large_captures/large_theme
time: [1.6528 ยตs 1.6650 ยตs 1.6784 ยตs]
change: [-91.684% -91.637% -91.593%] (p = 0.00 < 0.05)
Performance has improved.
Found 1 outliers among 100 measurements (1.00%)
1 (1.00%) low mild
```
For large themes and many capture names, the revised approach is much
faster.
With that in place, we can also add better fallbacks whenever we change
tokens, since e.g. a change from `@variable` to `@preproc` would
previously cause tokens to not be highlighted at all, whereas now we can
add fallbacks for such cases more efficiently. I'll add this later on to
this PR.
## Self-Review Checklist
<!-- Check before requesting review: -->
- [X] I've reviewed my own diff for quality, security, and reliability
- [ ] Unsafe blocks (if any) have justifying comments
- [ ] The content is consistent with the [UI/UX
checklist](https://github.com/zed-industries/zed/blob/main/CONTRIBUTING.md#uiux-checklist)
- [X] Tests cover the new/changed behavior
- [X] Performance impact has been considered and is acceptable
Release Notes:
- Improved resolution speed of theme highlight capture names. This might
change highlighting in some rare edge cases, but should overall make
highlighting more predicatable. Theme captures will now follow a strict
prefix matching, so e.g. function.call.decorator.jsx` will now be
matched by only `function`, `function.call`, `function.call.decorator`
and `function.call.decorator.jsx` with the most specific capture always
taking precedence.
---------
Co-authored-by: Piotr Osiewicz <24362066+osiewicz@users.noreply.github.com>
Co-authored-by: Gaauwe Rombouts <mail@grombouts.nl>
Cargo.lock | 1
crates/debugger_ui/src/session/running/variable_list.rs | 7
crates/editor/src/editor.rs | 6
crates/editor/src/semantic_tokens.rs | 5
crates/language/Cargo.toml | 5
crates/language/benches/highlight_map.rs | 144 +++++++++++
crates/language/src/highlight_map.rs | 34 -
crates/language_tools/src/highlights_tree_view.rs | 4
crates/onboarding/src/theme_preview.rs | 14
crates/theme/src/fallback_themes.rs | 126 ++++----
crates/theme/src/styles/syntax.rs | 125 ++++++---
crates/theme/src/theme.rs | 49 +--
12 files changed, 346 insertions(+), 174 deletions(-)
@@ -9331,6 +9331,7 @@ dependencies = [
"async-trait",
"clock",
"collections",
+ "criterion",
"ctor",
"diffy",
"ec4rs",
@@ -1076,7 +1076,12 @@ impl VariableList {
presentation_hint: Option<&VariablePresentationHint>,
cx: &Context<Self>,
) -> VariableColor {
- let syntax_color_for = |name| cx.theme().syntax().get(name).color;
+ let syntax_color_for = |name| {
+ cx.theme()
+ .syntax()
+ .style_for_name(name)
+ .and_then(|style| style.color)
+ };
let name = if self.disabled {
Some(Color::Disabled.color(cx))
} else {
@@ -601,7 +601,11 @@ pub fn make_inlay_hints_style(cx: &App) -> HighlightStyle {
.inlay_hints
.show_background;
- let mut style = cx.theme().syntax().get("hint");
+ let mut style = cx
+ .theme()
+ .syntax()
+ .style_for_name("hint")
+ .unwrap_or_default();
if style.color.is_none() {
style.color = Some(cx.theme().status().hint);
@@ -377,7 +377,10 @@ fn convert_token(
for rule in matching {
empty = false;
- let style = rule.style.iter().find_map(|style| theme.get_opt(style));
+ let style = rule
+ .style
+ .iter()
+ .find_map(|style| theme.style_for_name(style));
macro_rules! overwrite {
(
@@ -101,6 +101,11 @@ toml.workspace = true
unindent.workspace = true
util = { workspace = true, features = ["test-support"] }
zlog.workspace = true
+criterion.workspace = true
+
+[[bench]]
+name = "highlight_map"
+harness = false
[package.metadata.cargo-machete]
ignored = ["tracing"]
@@ -0,0 +1,144 @@
+use criterion::{BenchmarkId, Criterion, black_box, criterion_group, criterion_main};
+use gpui::rgba;
+use language::HighlightMap;
+use theme::SyntaxTheme;
+
+fn syntax_theme(highlight_names: &[&str]) -> SyntaxTheme {
+ SyntaxTheme::new(highlight_names.iter().enumerate().map(|(i, name)| {
+ let r = ((i * 37) % 256) as u8;
+ let g = ((i * 53) % 256) as u8;
+ let b = ((i * 71) % 256) as u8;
+ let color = rgba(u32::from_be_bytes([r, g, b, 0xff]));
+ (name.to_string(), color.into())
+ }))
+}
+
+static SMALL_THEME_KEYS: &[&str] = &[
+ "comment", "function", "keyword", "string", "type", "variable",
+];
+
+static LARGE_THEME_KEYS: &[&str] = &[
+ "attribute",
+ "boolean",
+ "comment",
+ "comment.doc",
+ "constant",
+ "constant.builtin",
+ "constructor",
+ "embedded",
+ "emphasis",
+ "emphasis.strong",
+ "function",
+ "function.builtin",
+ "function.method",
+ "function.method.builtin",
+ "function.special.definition",
+ "keyword",
+ "keyword.control",
+ "keyword.control.conditional",
+ "keyword.control.import",
+ "keyword.control.repeat",
+ "keyword.control.return",
+ "keyword.modifier",
+ "keyword.operator",
+ "label",
+ "link_text",
+ "link_uri",
+ "number",
+ "operator",
+ "property",
+ "punctuation",
+ "punctuation.bracket",
+ "punctuation.delimiter",
+ "punctuation.list_marker",
+ "punctuation.special",
+ "string",
+ "string.escape",
+ "string.regex",
+ "string.special",
+ "string.special.symbol",
+ "tag",
+ "text.literal",
+ "title",
+ "type",
+ "type.builtin",
+ "type.super",
+ "variable",
+ "variable.builtin",
+ "variable.member",
+ "variable.parameter",
+ "variable.special",
+];
+
+static SMALL_CAPTURE_NAMES: &[&str] = &[
+ "function",
+ "keyword",
+ "string.escape",
+ "type.builtin",
+ "variable.builtin",
+];
+
+static LARGE_CAPTURE_NAMES: &[&str] = &[
+ "attribute",
+ "boolean",
+ "comment",
+ "comment.doc",
+ "constant",
+ "constant.builtin",
+ "constructor",
+ "function",
+ "function.builtin",
+ "function.method",
+ "keyword",
+ "keyword.control",
+ "keyword.control.conditional",
+ "keyword.control.import",
+ "keyword.modifier",
+ "keyword.operator",
+ "label",
+ "number",
+ "operator",
+ "property",
+ "punctuation.bracket",
+ "punctuation.delimiter",
+ "punctuation.special",
+ "string",
+ "string.escape",
+ "string.regex",
+ "string.special",
+ "tag",
+ "type",
+ "type.builtin",
+ "variable",
+ "variable.builtin",
+ "variable.member",
+ "variable.parameter",
+];
+
+fn bench_highlight_map_new(c: &mut Criterion) {
+ let mut group = c.benchmark_group("HighlightMap::new");
+
+ for (capture_label, capture_names) in [
+ ("small_captures", SMALL_CAPTURE_NAMES as &[&str]),
+ ("large_captures", LARGE_CAPTURE_NAMES as &[&str]),
+ ] {
+ for (theme_label, theme_keys) in [
+ ("small_theme", SMALL_THEME_KEYS as &[&str]),
+ ("large_theme", LARGE_THEME_KEYS as &[&str]),
+ ] {
+ let theme = syntax_theme(theme_keys);
+ group.bench_with_input(
+ BenchmarkId::new(capture_label, theme_label),
+ &(capture_names, &theme),
+ |b, (capture_names, theme)| {
+ b.iter(|| HighlightMap::new(black_box(capture_names), black_box(theme)));
+ },
+ );
+ }
+ }
+
+ group.finish();
+}
+
+criterion_group!(benches, bench_highlight_map_new);
+criterion_main!(benches);
@@ -11,7 +11,7 @@ pub struct HighlightId(pub u32);
const DEFAULT_SYNTAX_HIGHLIGHT_ID: HighlightId = HighlightId(u32::MAX);
impl HighlightMap {
- pub(crate) fn new(capture_names: &[&str], theme: &SyntaxTheme) -> Self {
+ pub fn new(capture_names: &[&str], theme: &SyntaxTheme) -> Self {
// For each capture name in the highlight query, find the longest
// key in the theme's syntax styles that matches all of the
// dot-separated components of the capture name.
@@ -20,23 +20,8 @@ impl HighlightMap {
.iter()
.map(|capture_name| {
theme
- .highlights
- .iter()
- .enumerate()
- .filter_map(|(i, (key, _))| {
- let mut len = 0;
- let capture_parts = capture_name.split('.');
- for key_part in key.split('.') {
- if capture_parts.clone().any(|part| part == key_part) {
- len += 1;
- } else {
- return None;
- }
- }
- Some((i, len))
- })
- .max_by_key(|(_, len)| *len)
- .map_or(DEFAULT_SYNTAX_HIGHLIGHT_ID, |(i, _)| HighlightId(i as u32))
+ .highlight_id(capture_name)
+ .map_or(DEFAULT_SYNTAX_HIGHLIGHT_ID, HighlightId)
})
.collect(),
)
@@ -59,11 +44,11 @@ impl HighlightId {
}
pub fn style(&self, theme: &SyntaxTheme) -> Option<HighlightStyle> {
- theme.highlights.get(self.0 as usize).map(|entry| entry.1)
+ theme.get(self.0 as usize).cloned()
}
pub fn name<'a>(&self, theme: &'a SyntaxTheme) -> Option<&'a str> {
- theme.highlights.get(self.0 as usize).map(|e| e.0.as_str())
+ theme.get_capture_name(self.0 as usize)
}
}
@@ -86,8 +71,8 @@ mod tests {
#[test]
fn test_highlight_map() {
- let theme = SyntaxTheme {
- highlights: [
+ let theme = SyntaxTheme::new(
+ [
("function", rgba(0x100000ff)),
("function.method", rgba(0x200000ff)),
("function.async", rgba(0x300000ff)),
@@ -96,9 +81,8 @@ mod tests {
("variable", rgba(0x600000ff)),
]
.iter()
- .map(|(name, color)| (name.to_string(), (*color).into()))
- .collect(),
- };
+ .map(|(name, color)| (name.to_string(), (*color).into())),
+ );
let capture_names = &[
"function.special",
@@ -375,7 +375,9 @@ impl HighlightsTreeView {
rule.style
.iter()
.find(|style_name| {
- semantic_theme.get_opt(style_name).is_some()
+ semantic_theme
+ .style_for_name(style_name)
+ .is_some()
})
.map(|style_name| {
SharedString::from(style_name.clone())
@@ -87,13 +87,13 @@ impl ThemePreviewTile {
let colors = theme.colors();
let syntax = theme.syntax();
- let keyword_color = syntax.get("keyword").color;
- let function_color = syntax.get("function").color;
- let string_color = syntax.get("string").color;
- let comment_color = syntax.get("comment").color;
- let variable_color = syntax.get("variable").color;
- let type_color = syntax.get("type").color;
- let punctuation_color = syntax.get("punctuation").color;
+ let keyword_color = syntax.style_for_name("keyword").and_then(|s| s.color);
+ let function_color = syntax.style_for_name("function").and_then(|s| s.color);
+ let string_color = syntax.style_for_name("string").and_then(|s| s.color);
+ let comment_color = syntax.style_for_name("comment").and_then(|s| s.color);
+ let variable_color = syntax.style_for_name("variable").and_then(|s| s.color);
+ let type_color = syntax.style_for_name("type").and_then(|s| s.color);
+ let punctuation_color = syntax.style_for_name("punctuation").and_then(|s| s.color);
let syntax_colors = [
keyword_color,
@@ -314,70 +314,68 @@ pub(crate) fn zed_default_dark() -> Theme {
warning_border: yellow,
},
player,
- syntax: Arc::new(SyntaxTheme {
- highlights: vec![
- ("attribute".into(), purple.into()),
- ("boolean".into(), orange.into()),
- ("comment".into(), gray.into()),
- ("comment.doc".into(), gray.into()),
- ("constant".into(), yellow.into()),
- ("constructor".into(), blue.into()),
- ("embedded".into(), HighlightStyle::default()),
- (
- "emphasis".into(),
- HighlightStyle {
- font_style: Some(FontStyle::Italic),
- ..HighlightStyle::default()
- },
- ),
- (
- "emphasis.strong".into(),
- HighlightStyle {
- font_weight: Some(FontWeight::BOLD),
- ..HighlightStyle::default()
- },
- ),
- ("enum".into(), teal.into()),
- ("function".into(), blue.into()),
- ("function.method".into(), blue.into()),
- ("function.definition".into(), blue.into()),
- ("hint".into(), blue.into()),
- ("keyword".into(), purple.into()),
- ("label".into(), HighlightStyle::default()),
- ("link_text".into(), blue.into()),
- (
- "link_uri".into(),
- HighlightStyle {
- color: Some(teal),
- font_style: Some(FontStyle::Italic),
- ..HighlightStyle::default()
- },
- ),
- ("number".into(), orange.into()),
- ("operator".into(), HighlightStyle::default()),
- ("predictive".into(), HighlightStyle::default()),
- ("preproc".into(), HighlightStyle::default()),
- ("primary".into(), HighlightStyle::default()),
- ("property".into(), red.into()),
- ("punctuation".into(), HighlightStyle::default()),
- ("punctuation.bracket".into(), HighlightStyle::default()),
- ("punctuation.delimiter".into(), HighlightStyle::default()),
- ("punctuation.list_marker".into(), HighlightStyle::default()),
- ("punctuation.special".into(), HighlightStyle::default()),
- ("string".into(), green.into()),
- ("string.escape".into(), HighlightStyle::default()),
- ("string.regex".into(), red.into()),
- ("string.special".into(), HighlightStyle::default()),
- ("string.special.symbol".into(), HighlightStyle::default()),
- ("tag".into(), HighlightStyle::default()),
- ("text.literal".into(), HighlightStyle::default()),
- ("title".into(), HighlightStyle::default()),
- ("type".into(), teal.into()),
- ("variable".into(), HighlightStyle::default()),
- ("variable.special".into(), red.into()),
- ("variant".into(), HighlightStyle::default()),
- ],
- }),
+ syntax: Arc::new(SyntaxTheme::new(vec![
+ ("attribute".into(), purple.into()),
+ ("boolean".into(), orange.into()),
+ ("comment".into(), gray.into()),
+ ("comment.doc".into(), gray.into()),
+ ("constant".into(), yellow.into()),
+ ("constructor".into(), blue.into()),
+ ("embedded".into(), HighlightStyle::default()),
+ (
+ "emphasis".into(),
+ HighlightStyle {
+ font_style: Some(FontStyle::Italic),
+ ..HighlightStyle::default()
+ },
+ ),
+ (
+ "emphasis.strong".into(),
+ HighlightStyle {
+ font_weight: Some(FontWeight::BOLD),
+ ..HighlightStyle::default()
+ },
+ ),
+ ("enum".into(), teal.into()),
+ ("function".into(), blue.into()),
+ ("function.method".into(), blue.into()),
+ ("function.definition".into(), blue.into()),
+ ("hint".into(), blue.into()),
+ ("keyword".into(), purple.into()),
+ ("label".into(), HighlightStyle::default()),
+ ("link_text".into(), blue.into()),
+ (
+ "link_uri".into(),
+ HighlightStyle {
+ color: Some(teal),
+ font_style: Some(FontStyle::Italic),
+ ..HighlightStyle::default()
+ },
+ ),
+ ("number".into(), orange.into()),
+ ("operator".into(), HighlightStyle::default()),
+ ("predictive".into(), HighlightStyle::default()),
+ ("preproc".into(), HighlightStyle::default()),
+ ("primary".into(), HighlightStyle::default()),
+ ("property".into(), red.into()),
+ ("punctuation".into(), HighlightStyle::default()),
+ ("punctuation.bracket".into(), HighlightStyle::default()),
+ ("punctuation.delimiter".into(), HighlightStyle::default()),
+ ("punctuation.list_marker".into(), HighlightStyle::default()),
+ ("punctuation.special".into(), HighlightStyle::default()),
+ ("string".into(), green.into()),
+ ("string.escape".into(), HighlightStyle::default()),
+ ("string.regex".into(), red.into()),
+ ("string.special".into(), HighlightStyle::default()),
+ ("string.special.symbol".into(), HighlightStyle::default()),
+ ("tag".into(), HighlightStyle::default()),
+ ("text.literal".into(), HighlightStyle::default()),
+ ("title".into(), HighlightStyle::default()),
+ ("type".into(), teal.into()),
+ ("variable".into(), HighlightStyle::default()),
+ ("variable.special".into(), red.into()),
+ ("variant".into(), HighlightStyle::default()),
+ ])),
},
}
}
@@ -1,15 +1,38 @@
#![allow(missing_docs)]
-use std::sync::Arc;
+use std::{
+ collections::{BTreeMap, btree_map::Entry},
+ sync::Arc,
+};
-use gpui::{HighlightStyle, Hsla};
+use gpui::HighlightStyle;
+#[cfg(any(test, feature = "test-support"))]
+use gpui::Hsla;
#[derive(Debug, PartialEq, Eq, Clone, Default)]
pub struct SyntaxTheme {
- pub highlights: Vec<(String, HighlightStyle)>,
+ pub(self) highlights: Vec<HighlightStyle>,
+ pub(self) capture_name_map: BTreeMap<String, usize>,
}
impl SyntaxTheme {
+ pub fn new(highlights: impl IntoIterator<Item = (String, HighlightStyle)>) -> Self {
+ let (capture_names, highlights) = highlights.into_iter().unzip();
+
+ Self {
+ capture_name_map: Self::create_capture_name_map(capture_names),
+ highlights,
+ }
+ }
+
+ fn create_capture_name_map(highlights: Vec<String>) -> BTreeMap<String, usize> {
+ highlights
+ .into_iter()
+ .enumerate()
+ .map(|(i, key)| (key, i))
+ .collect()
+ }
+
#[cfg(any(test, feature = "test-support"))]
pub fn new_test(colors: impl IntoIterator<Item = (&'static str, Hsla)>) -> Self {
Self::new_test_styles(colors.into_iter().map(|(key, color)| {
@@ -27,34 +50,45 @@ impl SyntaxTheme {
pub fn new_test_styles(
colors: impl IntoIterator<Item = (&'static str, HighlightStyle)>,
) -> Self {
- Self {
- highlights: colors
+ Self::new(
+ colors
.into_iter()
- .map(|(key, style)| (key.to_owned(), style))
- .collect(),
- }
+ .map(|(key, style)| (key.to_owned(), style)),
+ )
}
- pub fn get(&self, name: &str) -> HighlightStyle {
- self.highlights
- .iter()
- .find_map(|entry| if entry.0 == name { Some(entry.1) } else { None })
- .unwrap_or_default()
+ pub fn get(&self, highlight_index: usize) -> Option<&HighlightStyle> {
+ self.highlights.get(highlight_index)
}
- pub fn get_opt(&self, name: &str) -> Option<HighlightStyle> {
- self.highlights
- .iter()
- .find_map(|entry| if entry.0 == name { Some(entry.1) } else { None })
+ pub fn style_for_name(&self, name: &str) -> Option<HighlightStyle> {
+ self.capture_name_map
+ .get(name)
+ .map(|highlight_idx| self.highlights[*highlight_idx])
}
- pub fn color(&self, name: &str) -> Hsla {
- self.get(name).color.unwrap_or_default()
+ pub fn get_capture_name(&self, idx: usize) -> Option<&str> {
+ self.capture_name_map
+ .iter()
+ .find(|(_, value)| **value == idx)
+ .map(|(key, _)| key.as_ref())
}
- pub fn highlight_id(&self, name: &str) -> Option<u32> {
- let ix = self.highlights.iter().position(|entry| entry.0 == name)?;
- Some(ix as u32)
+ pub fn highlight_id(&self, capture_name: &str) -> Option<u32> {
+ self.capture_name_map
+ .range::<str, _>((
+ capture_name.split(".").next().map_or(
+ std::ops::Bound::Included(capture_name),
+ std::ops::Bound::Included,
+ ),
+ std::ops::Bound::Included(capture_name),
+ ))
+ .rfind(|(prefix, _)| {
+ capture_name
+ .strip_prefix(*prefix)
+ .is_some_and(|remainder| remainder.is_empty() || remainder.starts_with('.'))
+ })
+ .map(|(_, index)| *index as u32)
}
/// Returns a new [`Arc<SyntaxTheme>`] with the given syntax styles merged in.
@@ -63,33 +97,36 @@ impl SyntaxTheme {
return base;
}
- let mut merged_highlights = base.highlights.clone();
+ let mut base = Arc::try_unwrap(base).unwrap_or_else(|base| (*base).clone());
for (name, highlight) in user_syntax_styles {
- if let Some((_, existing_highlight)) = merged_highlights
- .iter_mut()
- .find(|(existing_name, _)| existing_name == &name)
- {
- existing_highlight.color = highlight.color.or(existing_highlight.color);
- existing_highlight.font_weight =
- highlight.font_weight.or(existing_highlight.font_weight);
- existing_highlight.font_style =
- highlight.font_style.or(existing_highlight.font_style);
- existing_highlight.background_color = highlight
- .background_color
- .or(existing_highlight.background_color);
- existing_highlight.underline = highlight.underline.or(existing_highlight.underline);
- existing_highlight.strikethrough =
- highlight.strikethrough.or(existing_highlight.strikethrough);
- existing_highlight.fade_out = highlight.fade_out.or(existing_highlight.fade_out);
- } else {
- merged_highlights.push((name, highlight));
+ match base.capture_name_map.entry(name) {
+ Entry::Occupied(entry) => {
+ if let Some(existing_highlight) = base.highlights.get_mut(*entry.get()) {
+ existing_highlight.color = highlight.color.or(existing_highlight.color);
+ existing_highlight.font_weight =
+ highlight.font_weight.or(existing_highlight.font_weight);
+ existing_highlight.font_style =
+ highlight.font_style.or(existing_highlight.font_style);
+ existing_highlight.background_color = highlight
+ .background_color
+ .or(existing_highlight.background_color);
+ existing_highlight.underline =
+ highlight.underline.or(existing_highlight.underline);
+ existing_highlight.strikethrough =
+ highlight.strikethrough.or(existing_highlight.strikethrough);
+ existing_highlight.fade_out =
+ highlight.fade_out.or(existing_highlight.fade_out);
+ }
+ }
+ Entry::Vacant(vacant) => {
+ vacant.insert(base.highlights.len());
+ base.highlights.push(highlight);
+ }
}
}
- Arc::new(Self {
- highlights: merged_highlights,
- })
+ Arc::new(base)
}
}
@@ -258,30 +258,25 @@ impl ThemeFamily {
};
refined_accent_colors.merge(&theme.style.accents);
- let syntax_highlights = theme
- .style
- .syntax
- .iter()
- .map(|(syntax_token, highlight)| {
- (
- syntax_token.clone(),
- HighlightStyle {
- color: highlight
- .color
- .as_ref()
- .and_then(|color| try_parse_color(color).ok()),
- background_color: highlight
- .background_color
- .as_ref()
- .and_then(|color| try_parse_color(color).ok()),
- font_style: highlight.font_style.map(|s| s.into_gpui()),
- font_weight: highlight.font_weight.map(|w| w.into_gpui()),
- ..Default::default()
- },
- )
- })
- .collect::<Vec<_>>();
- let syntax_theme = SyntaxTheme::merge(Arc::new(SyntaxTheme::default()), syntax_highlights);
+ let syntax_highlights = theme.style.syntax.iter().map(|(syntax_token, highlight)| {
+ (
+ syntax_token.clone(),
+ HighlightStyle {
+ color: highlight
+ .color
+ .as_ref()
+ .and_then(|color| try_parse_color(color).ok()),
+ background_color: highlight
+ .background_color
+ .as_ref()
+ .and_then(|color| try_parse_color(color).ok()),
+ font_style: highlight.font_style.map(|s| s.into_gpui()),
+ font_weight: highlight.font_weight.map(|w| w.into_gpui()),
+ ..Default::default()
+ },
+ )
+ });
+ let syntax_theme = Arc::new(SyntaxTheme::new(syntax_highlights));
let window_background_appearance = theme
.style
@@ -381,12 +376,6 @@ impl Theme {
&self.styles.status
}
- /// Returns the color for the syntax node with the given name.
- #[inline(always)]
- pub fn syntax_color(&self, name: &str) -> Hsla {
- self.syntax().color(name)
- }
-
/// Returns the [`Appearance`] for the theme.
#[inline(always)]
pub fn appearance(&self) -> Appearance {