<img width="497" alt="image" src="https://github.com/zed-industries/zed/assets/482957/94e94326-fb3c-4f9b-b4d9-7dd6f6f8d537"> e.g. ``` /search --9 foobar ``` Release Notes: - N/A
196 lines
6.1 KiB
Rust
196 lines
6.1 KiB
Rust
use std::sync::Arc;
|
|
|
|
use gpui::{HighlightStyle, Hsla};
|
|
|
|
#[derive(Debug, PartialEq, Eq, Clone, Default)]
|
|
pub struct SyntaxTheme {
|
|
pub highlights: Vec<(String, HighlightStyle)>,
|
|
}
|
|
|
|
impl SyntaxTheme {
|
|
#[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)| {
|
|
(
|
|
key,
|
|
HighlightStyle {
|
|
color: Some(color),
|
|
..Default::default()
|
|
},
|
|
)
|
|
}))
|
|
}
|
|
|
|
#[cfg(any(test, feature = "test-support"))]
|
|
pub fn new_test_styles(
|
|
colors: impl IntoIterator<Item = (&'static str, HighlightStyle)>,
|
|
) -> Self {
|
|
Self {
|
|
highlights: colors
|
|
.into_iter()
|
|
.map(|(key, style)| (key.to_owned(), style))
|
|
.collect(),
|
|
}
|
|
}
|
|
|
|
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 color(&self, name: &str) -> Hsla {
|
|
self.get(name).color.unwrap_or_default()
|
|
}
|
|
|
|
pub fn highlight_id(&self, name: &str) -> Option<u32> {
|
|
let ix = self.highlights.iter().position(|entry| entry.0 == name)?;
|
|
Some(ix as u32)
|
|
}
|
|
|
|
/// Returns a new [`Arc<SyntaxTheme>`] with the given syntax styles merged in.
|
|
pub fn merge(base: Arc<Self>, user_syntax_styles: Vec<(String, HighlightStyle)>) -> Arc<Self> {
|
|
if user_syntax_styles.is_empty() {
|
|
return base;
|
|
}
|
|
|
|
let mut merged_highlights = base.highlights.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));
|
|
}
|
|
}
|
|
|
|
Arc::new(Self {
|
|
highlights: merged_highlights,
|
|
})
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use gpui::FontStyle;
|
|
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_syntax_theme_merge() {
|
|
// Merging into an empty `SyntaxTheme` keeps all the user-defined styles.
|
|
let syntax_theme = SyntaxTheme::merge(
|
|
Arc::new(SyntaxTheme::new_test([])),
|
|
vec![
|
|
(
|
|
"foo".to_string(),
|
|
HighlightStyle {
|
|
color: Some(gpui::red()),
|
|
..Default::default()
|
|
},
|
|
),
|
|
(
|
|
"foo.bar".to_string(),
|
|
HighlightStyle {
|
|
color: Some(gpui::green()),
|
|
..Default::default()
|
|
},
|
|
),
|
|
],
|
|
);
|
|
assert_eq!(
|
|
syntax_theme,
|
|
Arc::new(SyntaxTheme::new_test([
|
|
("foo", gpui::red()),
|
|
("foo.bar", gpui::green())
|
|
]))
|
|
);
|
|
|
|
// Merging empty user-defined styles keeps all the base styles.
|
|
let syntax_theme = SyntaxTheme::merge(
|
|
Arc::new(SyntaxTheme::new_test([
|
|
("foo", gpui::blue()),
|
|
("foo.bar", gpui::red()),
|
|
])),
|
|
Vec::new(),
|
|
);
|
|
assert_eq!(
|
|
syntax_theme,
|
|
Arc::new(SyntaxTheme::new_test([
|
|
("foo", gpui::blue()),
|
|
("foo.bar", gpui::red())
|
|
]))
|
|
);
|
|
|
|
let syntax_theme = SyntaxTheme::merge(
|
|
Arc::new(SyntaxTheme::new_test([
|
|
("foo", gpui::red()),
|
|
("foo.bar", gpui::green()),
|
|
])),
|
|
vec![(
|
|
"foo.bar".to_string(),
|
|
HighlightStyle {
|
|
color: Some(gpui::yellow()),
|
|
..Default::default()
|
|
},
|
|
)],
|
|
);
|
|
assert_eq!(
|
|
syntax_theme,
|
|
Arc::new(SyntaxTheme::new_test([
|
|
("foo", gpui::red()),
|
|
("foo.bar", gpui::yellow())
|
|
]))
|
|
);
|
|
|
|
let syntax_theme = SyntaxTheme::merge(
|
|
Arc::new(SyntaxTheme::new_test([
|
|
("foo", gpui::red()),
|
|
("foo.bar", gpui::green()),
|
|
])),
|
|
vec![(
|
|
"foo.bar".to_string(),
|
|
HighlightStyle {
|
|
font_style: Some(FontStyle::Italic),
|
|
..Default::default()
|
|
},
|
|
)],
|
|
);
|
|
assert_eq!(
|
|
syntax_theme,
|
|
Arc::new(SyntaxTheme::new_test_styles([
|
|
(
|
|
"foo",
|
|
HighlightStyle {
|
|
color: Some(gpui::red()),
|
|
..Default::default()
|
|
}
|
|
),
|
|
(
|
|
"foo.bar",
|
|
HighlightStyle {
|
|
color: Some(gpui::green()),
|
|
font_style: Some(FontStyle::Italic),
|
|
..Default::default()
|
|
}
|
|
)
|
|
]))
|
|
);
|
|
}
|
|
}
|