registry.rs

  1use std::collections::HashMap;
  2use std::sync::Arc;
  3
  4use anyhow::{anyhow, Result};
  5use gpui::{HighlightStyle, SharedString};
  6use refineable::Refineable;
  7
  8use crate::{
  9    zed_pro_family, Appearance, PlayerColors, StatusColors, SyntaxTheme, SystemColors, Theme,
 10    ThemeColors, ThemeFamily, ThemeStyles, UserTheme, UserThemeFamily,
 11};
 12
 13pub struct ThemeRegistry {
 14    themes: HashMap<SharedString, Arc<Theme>>,
 15}
 16
 17impl ThemeRegistry {
 18    fn insert_theme_families(&mut self, families: impl IntoIterator<Item = ThemeFamily>) {
 19        for family in families.into_iter() {
 20            self.insert_themes(family.themes);
 21        }
 22    }
 23
 24    fn insert_themes(&mut self, themes: impl IntoIterator<Item = Theme>) {
 25        for theme in themes.into_iter() {
 26            self.themes.insert(theme.name.clone(), Arc::new(theme));
 27        }
 28    }
 29
 30    fn insert_user_theme_familes(&mut self, families: impl IntoIterator<Item = UserThemeFamily>) {
 31        for family in families.into_iter() {
 32            self.insert_user_themes(family.themes);
 33        }
 34    }
 35
 36    fn insert_user_themes(&mut self, themes: impl IntoIterator<Item = UserTheme>) {
 37        self.insert_themes(themes.into_iter().map(|user_theme| {
 38            let mut theme_colors = match user_theme.appearance {
 39                Appearance::Light => ThemeColors::default_light(),
 40                Appearance::Dark => ThemeColors::default_dark(),
 41            };
 42            theme_colors.refine(&user_theme.styles.colors);
 43
 44            let mut status_colors = StatusColors::default();
 45            status_colors.refine(&user_theme.styles.status);
 46
 47            let mut syntax_colors = match user_theme.appearance {
 48                Appearance::Light => SyntaxTheme::default_light(),
 49                Appearance::Dark => SyntaxTheme::default_dark(),
 50            };
 51            if let Some(user_syntax) = user_theme.styles.syntax {
 52                syntax_colors.highlights = user_syntax
 53                    .highlights
 54                    .iter()
 55                    .map(|(syntax_token, highlight)| {
 56                        (
 57                            syntax_token.clone(),
 58                            HighlightStyle {
 59                                color: highlight.color,
 60                                font_style: highlight.font_style.map(Into::into),
 61                                font_weight: highlight.font_weight.map(Into::into),
 62                                ..Default::default()
 63                            },
 64                        )
 65                    })
 66                    .collect::<Vec<_>>();
 67            }
 68
 69            Theme {
 70                id: uuid::Uuid::new_v4().to_string(),
 71                name: user_theme.name.into(),
 72                appearance: user_theme.appearance,
 73                styles: ThemeStyles {
 74                    system: SystemColors::default(),
 75                    colors: theme_colors,
 76                    status: status_colors,
 77                    player: PlayerColors::default(),
 78                    syntax: Arc::new(syntax_colors),
 79                },
 80            }
 81        }));
 82    }
 83
 84    pub fn list_names(&self, _staff: bool) -> impl Iterator<Item = SharedString> + '_ {
 85        self.themes.keys().cloned()
 86    }
 87
 88    pub fn list(&self, _staff: bool) -> impl Iterator<Item = SharedString> + '_ {
 89        self.themes.values().map(|theme| theme.name.clone())
 90    }
 91
 92    pub fn get(&self, name: &str) -> Result<Arc<Theme>> {
 93        self.themes
 94            .get(name)
 95            .ok_or_else(|| anyhow!("theme not found: {}", name))
 96            .cloned()
 97    }
 98}
 99
100impl Default for ThemeRegistry {
101    fn default() -> Self {
102        let mut this = Self {
103            themes: HashMap::default(),
104        };
105
106        this.insert_theme_families([zed_pro_family()]);
107
108        #[cfg(not(feature = "importing-themes"))]
109        this.insert_user_theme_familes(crate::all_user_themes());
110
111        this
112    }
113}