190 lines · 5.9 KB · Rust
RawDownload
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()    }     /// 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()                    }                )            ]))        );    }}