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    one_themes::one_family, zed_pro_family, Appearance, PlayerColors, StatusColors, SyntaxTheme,
 10    SystemColors, Theme, 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    #[allow(unused)]
 31    fn insert_user_theme_familes(&mut self, families: impl IntoIterator<Item = UserThemeFamily>) {
 32        for family in families.into_iter() {
 33            self.insert_user_themes(family.themes);
 34        }
 35    }
 36
 37    #[allow(unused)]
 38    fn insert_user_themes(&mut self, themes: impl IntoIterator<Item = UserTheme>) {
 39        self.insert_themes(themes.into_iter().map(|user_theme| {
 40            let mut theme_colors = match user_theme.appearance {
 41                Appearance::Light => ThemeColors::light(),
 42                Appearance::Dark => ThemeColors::dark(),
 43            };
 44            theme_colors.refine(&user_theme.styles.colors);
 45
 46            let mut status_colors = StatusColors::dark();
 47            status_colors.refine(&user_theme.styles.status);
 48
 49            let mut syntax_colors = match user_theme.appearance {
 50                Appearance::Light => SyntaxTheme::light(),
 51                Appearance::Dark => SyntaxTheme::dark(),
 52            };
 53            if let Some(user_syntax) = user_theme.styles.syntax {
 54                syntax_colors.highlights = user_syntax
 55                    .highlights
 56                    .iter()
 57                    .map(|(syntax_token, highlight)| {
 58                        (
 59                            syntax_token.clone(),
 60                            HighlightStyle {
 61                                color: highlight.color,
 62                                font_style: highlight.font_style.map(Into::into),
 63                                font_weight: highlight.font_weight.map(Into::into),
 64                                ..Default::default()
 65                            },
 66                        )
 67                    })
 68                    .collect::<Vec<_>>();
 69            }
 70
 71            Theme {
 72                id: uuid::Uuid::new_v4().to_string(),
 73                name: user_theme.name.into(),
 74                appearance: user_theme.appearance,
 75                styles: ThemeStyles {
 76                    system: SystemColors::default(),
 77                    colors: theme_colors,
 78                    status: status_colors,
 79                    player: match user_theme.appearance {
 80                        Appearance::Light => PlayerColors::light(),
 81                        Appearance::Dark => PlayerColors::dark(),
 82                    },
 83                    syntax: Arc::new(syntax_colors),
 84                },
 85            }
 86        }));
 87    }
 88
 89    pub fn clear(&mut self) {
 90        self.themes.clear();
 91    }
 92
 93    pub fn list_names(&self, _staff: bool) -> impl Iterator<Item = SharedString> + '_ {
 94        self.themes.keys().cloned()
 95    }
 96
 97    pub fn list(&self, _staff: bool) -> impl Iterator<Item = SharedString> + '_ {
 98        self.themes.values().map(|theme| theme.name.clone())
 99    }
100
101    pub fn get(&self, name: &str) -> Result<Arc<Theme>> {
102        self.themes
103            .get(name)
104            .ok_or_else(|| anyhow!("theme not found: {}", name))
105            .cloned()
106    }
107
108    pub fn load_user_themes(&mut self) {
109        #[cfg(not(feature = "importing-themes"))]
110        self.insert_user_theme_familes(crate::all_user_themes());
111    }
112}
113
114impl Default for ThemeRegistry {
115    fn default() -> Self {
116        let mut this = Self {
117            themes: HashMap::default(),
118        };
119
120        this.insert_theme_families([zed_pro_family(), one_family()]);
121
122        this
123    }
124}