Test bundled themes and store names on themes

Max Brunsfeld and Nathan Sobo created

Co-Authored-By: Nathan Sobo <nathan@zed.dev>

Change summary

zed/assets/themes/light.toml | 32 ++++++++++++++++----------------
zed/src/settings.rs          |  4 ++--
zed/src/theme.rs             | 26 +++++++++++++++++++++++---
3 files changed, 41 insertions(+), 21 deletions(-)

Detailed changes

zed/assets/themes/light.toml 🔗

@@ -1,21 +1,21 @@
 extends = "_base"
 
 [variables]
-elevation_1 = 0xffffff
-elevation_2 = 0xf3f3f3
-elevation_3 = 0xececec
-elevation_4 = 0x3a3b3c
-text_dull = 0xacacac
-text_bright = 0x111111
-text_normal = 0x333333
+elevation_1 = "#ffffff"
+elevation_2 = "#f3f3f3"
+elevation_3 = "#ececec"
+elevation_4 = "#3a3b3c"
+text_dull = "#acacac"
+text_bright = "#111111"
+text_normal = "#333333"
 
 [syntax]
-keyword = 0x0000fa
-function = 0x795e26
-string = 0xa82121
-type = 0x267f29
-number = 0xb5cea8
-comment = 0x6a9955
-property = 0x4e94ce
-variant = 0x4fc1ff
-constant = 0x9cdcfe
+keyword = "#0000fa"
+function = "#795e26"
+string = "#a82121"
+type = "#267f29"
+number = "#b5cea8"
+comment = "#6a9955"
+property = "#4e94ce"
+variant = "#4fc1ff"
+constant = "#9cdcfe"

zed/src/settings.rs 🔗

@@ -1,4 +1,4 @@
-use crate::theme;
+use crate::theme::{self, DEFAULT_THEME_NAME};
 use anyhow::Result;
 use gpui::font_cache::{FamilyId, FontCache};
 use postage::watch;
@@ -48,7 +48,7 @@ pub fn channel_with_themes(
     font_cache: &FontCache,
     themes: &ThemeRegistry,
 ) -> Result<(watch::Sender<Settings>, watch::Receiver<Settings>)> {
-    let theme = match themes.get("dark") {
+    let theme = match themes.get(DEFAULT_THEME_NAME) {
         Ok(theme) => dbg!(theme),
         Err(err) => {
             panic!("failed to deserialize default theme: {:?}", err)

zed/src/theme.rs 🔗

@@ -12,6 +12,7 @@ use serde_json as json;
 use std::{cmp::Ordering, collections::HashMap, sync::Arc};
 
 const DEFAULT_HIGHLIGHT_ID: HighlightId = HighlightId(u32::MAX);
+pub const DEFAULT_THEME_NAME: &'static str = "dark";
 
 pub struct ThemeRegistry {
     assets: Box<dyn AssetSource>,
@@ -27,6 +28,8 @@ pub struct HighlightId(u32);
 
 #[derive(Debug, Default, Deserialize)]
 pub struct Theme {
+    #[serde(default)]
+    pub name: String,
     pub ui: Ui,
     pub editor: Editor,
     #[serde(deserialize_with = "deserialize_syntax_theme")]
@@ -129,9 +132,9 @@ impl ThemeRegistry {
         }
 
         let theme_data = self.load(name)?;
-        let theme = Arc::new(serde_json::from_value::<Theme>(
-            theme_data.as_ref().clone(),
-        )?);
+        let mut theme = serde_json::from_value::<Theme>(theme_data.as_ref().clone())?;
+        theme.name = name.into();
+        let theme = Arc::new(theme);
         self.themes.lock().insert(name.to_string(), theme.clone());
         Ok(theme)
     }
@@ -455,8 +458,24 @@ where
 
 #[cfg(test)]
 mod tests {
+    use crate::assets::Assets;
+
     use super::*;
 
+    #[test]
+    fn test_bundled_themes() {
+        let registry = ThemeRegistry::new(Assets);
+        let mut has_default_theme = false;
+        for theme_name in registry.list() {
+            let theme = registry.get(&theme_name).unwrap();
+            if theme.name == DEFAULT_THEME_NAME {
+                has_default_theme = true;
+            }
+            assert_eq!(theme.name, theme_name);
+        }
+        assert!(has_default_theme);
+    }
+
     #[test]
     fn test_theme_extension() {
         let assets = TestAssets(&[
@@ -546,6 +565,7 @@ mod tests {
     #[test]
     fn test_highlight_map() {
         let theme = Theme {
+            name: "test".into(),
             ui: Default::default(),
             editor: Default::default(),
             syntax: [