use std::collections::HashMap; use std::sync::Arc; use anyhow::{anyhow, Result}; use gpui::{HighlightStyle, SharedString}; use refineable::Refineable; use crate::{ one_themes::one_family, zed_pro_family, Appearance, PlayerColors, StatusColors, SyntaxTheme, SystemColors, Theme, ThemeColors, ThemeFamily, ThemeStyles, UserTheme, UserThemeFamily, }; pub struct ThemeRegistry { themes: HashMap>, } impl ThemeRegistry { fn insert_theme_families(&mut self, families: impl IntoIterator) { for family in families.into_iter() { self.insert_themes(family.themes); } } fn insert_themes(&mut self, themes: impl IntoIterator) { for theme in themes.into_iter() { self.themes.insert(theme.name.clone(), Arc::new(theme)); } } #[allow(unused)] fn insert_user_theme_familes(&mut self, families: impl IntoIterator) { for family in families.into_iter() { self.insert_user_themes(family.themes); } } #[allow(unused)] fn insert_user_themes(&mut self, themes: impl IntoIterator) { self.insert_themes(themes.into_iter().map(|user_theme| { let mut theme_colors = match user_theme.appearance { Appearance::Light => ThemeColors::light(), Appearance::Dark => ThemeColors::dark(), }; theme_colors.refine(&user_theme.styles.colors); let mut status_colors = StatusColors::dark(); status_colors.refine(&user_theme.styles.status); let mut syntax_colors = match user_theme.appearance { Appearance::Light => SyntaxTheme::light(), Appearance::Dark => SyntaxTheme::dark(), }; if let Some(user_syntax) = user_theme.styles.syntax { syntax_colors.highlights = user_syntax .highlights .iter() .map(|(syntax_token, highlight)| { ( syntax_token.clone(), HighlightStyle { color: highlight.color, font_style: highlight.font_style.map(Into::into), font_weight: highlight.font_weight.map(Into::into), ..Default::default() }, ) }) .collect::>(); } Theme { id: uuid::Uuid::new_v4().to_string(), name: user_theme.name.into(), appearance: user_theme.appearance, styles: ThemeStyles { system: SystemColors::default(), colors: theme_colors, status: status_colors, player: match user_theme.appearance { Appearance::Light => PlayerColors::light(), Appearance::Dark => PlayerColors::dark(), }, syntax: Arc::new(syntax_colors), }, } })); } pub fn clear(&mut self) { self.themes.clear(); } pub fn list_names(&self, _staff: bool) -> impl Iterator + '_ { self.themes.keys().cloned() } pub fn list(&self, _staff: bool) -> impl Iterator + '_ { self.themes.values().map(|theme| theme.name.clone()) } pub fn get(&self, name: &str) -> Result> { self.themes .get(name) .ok_or_else(|| anyhow!("theme not found: {}", name)) .cloned() } pub fn load_user_themes(&mut self) { #[cfg(not(feature = "importing-themes"))] self.insert_user_theme_familes(crate::all_user_themes()); } } impl Default for ThemeRegistry { fn default() -> Self { let mut this = Self { themes: HashMap::default(), }; this.insert_theme_families([zed_pro_family(), one_family()]); this } }