Emit all themes at once

Marshall Bowers created

Change summary

Cargo.lock                             |  1 
crates/theme2/src/themes/one_dark.rs   | 42 ++++++++++++++++++++++------
crates/theme2/src/themes/sandcastle.rs | 42 ++++++++++++++++++++++------
crates/theme_converter/Cargo.toml      |  1 
crates/theme_converter/src/main.rs     | 37 ++++++++++++++++++++----
5 files changed, 98 insertions(+), 25 deletions(-)

Detailed changes

Cargo.lock 🔗

@@ -8740,6 +8740,7 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "clap 4.4.4",
+ "convert_case 0.6.0",
  "gpui2",
  "log",
  "rust-embed",

crates/theme2/src/themes/one_dark.rs 🔗

@@ -1,131 +1,85 @@
-use gpui2::rgba;
-
-use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
-
-pub fn one_dark() -> Theme {
-    Theme {
-        metadata: ThemeMetadata {
-            name: "One Dark".into(),
-            is_light: false,
+Theme {
+    metadata: ThemeMetadata {
+        name: "One Dark".into(),
+        is_light: false,
+    },
+    transparent: rgba(0x00000000).into(),
+    mac_os_traffic_light_red: rgba(0xec695eff).into(),
+    mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+    mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+    border: rgba(0x464b57ff).into(),
+    border_variant: rgba(0x464b57ff).into(),
+    border_focused: rgba(0x293b5bff).into(),
+    border_transparent: rgba(0x00000000).into(),
+    elevated_surface: rgba(0x3b414dff).into(),
+    surface: rgba(0x2f343eff).into(),
+    background: rgba(0x3b414dff).into(),
+    filled_element: rgba(0x3b414dff).into(),
+    filled_element_hover: rgba(0xffffff1e).into(),
+    filled_element_active: rgba(0xffffff28).into(),
+    filled_element_selected: rgba(0x18243dff).into(),
+    filled_element_disabled: rgba(0x00000000).into(),
+    ghost_element: rgba(0x00000000).into(),
+    ghost_element_hover: rgba(0xffffff14).into(),
+    ghost_element_active: rgba(0xffffff1e).into(),
+    ghost_element_selected: rgba(0x18243dff).into(),
+    ghost_element_disabled: rgba(0x00000000).into(),
+    text: rgba(0xc8ccd4ff).into(),
+    text_muted: rgba(0x838994ff).into(),
+    text_placeholder: rgba(0xd07277ff).into(),
+    text_disabled: rgba(0x555a63ff).into(),
+    text_accent: rgba(0x74ade8ff).into(),
+    icon_muted: rgba(0x838994ff).into(),
+    syntax: SyntaxTheme {

crates/theme2/src/themes/sandcastle.rs 🔗

@@ -1,130 +1,85 @@
-use gpui2::rgba;
-
-use crate::{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata};
-
-pub fn sandcastle() -> Theme {
-    Theme {
-        metadata: ThemeMetadata {
-            name: "Sandcastle".into(),
-            is_light: false,
+Theme {
+    metadata: ThemeMetadata {
+        name: "Sandcastle".into(),
+        is_light: false,
+    },
+    transparent: rgba(0x00000000).into(),
+    mac_os_traffic_light_red: rgba(0xec695eff).into(),
+    mac_os_traffic_light_yellow: rgba(0xf4bf4eff).into(),
+    mac_os_traffic_light_green: rgba(0x61c553ff).into(),
+    border: rgba(0x3d4350ff).into(),
+    border_variant: rgba(0x3d4350ff).into(),
+    border_focused: rgba(0x223131ff).into(),
+    border_transparent: rgba(0x00000000).into(),
+    elevated_surface: rgba(0x333944ff).into(),
+    surface: rgba(0x2b3038ff).into(),
+    background: rgba(0x333944ff).into(),
+    filled_element: rgba(0x333944ff).into(),
+    filled_element_hover: rgba(0xffffff1e).into(),
+    filled_element_active: rgba(0xffffff28).into(),
+    filled_element_selected: rgba(0x171e1eff).into(),
+    filled_element_disabled: rgba(0x00000000).into(),
+    ghost_element: rgba(0x00000000).into(),
+    ghost_element_hover: rgba(0xffffff14).into(),
+    ghost_element_active: rgba(0xffffff1e).into(),
+    ghost_element_selected: rgba(0x171e1eff).into(),
+    ghost_element_disabled: rgba(0x00000000).into(),
+    text: rgba(0xfdf4c1ff).into(),
+    text_muted: rgba(0xa69782ff).into(),
+    text_placeholder: rgba(0xb3627aff).into(),
+    text_disabled: rgba(0x827568ff).into(),
+    text_accent: rgba(0x518b8bff).into(),
+    icon_muted: rgba(0xa69782ff).into(),
+    syntax: SyntaxTheme {

crates/theme_converter/Cargo.toml 🔗

@@ -9,6 +9,7 @@ publish = false
 [dependencies]
 anyhow.workspace = true
 clap = { version = "4.4", features = ["derive", "string"] }
+convert_case = "0.6.0"
 gpui2 = { path = "../gpui2" }
 log.workspace = true
 rust-embed.workspace = true

crates/theme_converter/src/main.rs 🔗

@@ -3,9 +3,14 @@ mod theme_printer;
 use std::borrow::Cow;
 use std::collections::HashMap;
 use std::fmt::{self, Debug};
+use std::fs::{self, File};
+use std::io::Write;
+use std::path::PathBuf;
+use std::str::FromStr;
 
 use anyhow::{anyhow, Context, Result};
 use clap::Parser;
+use convert_case::{Case, Casing};
 use gpui2::{hsla, rgb, serde_json, AssetSource, Hsla, SharedString};
 use log::LevelFilter;
 use rust_embed::RustEmbed;
@@ -26,13 +31,31 @@ struct Args {
 fn main() -> Result<()> {
     SimpleLogger::init(LevelFilter::Info, Default::default()).expect("could not initialize logger");
 
-    let args = Args::parse();
+    // let args = Args::parse();
 
-    let (json_theme, legacy_theme) = load_theme(args.theme)?;
+    let themes_path = PathBuf::from_str("crates/theme2/src/themes")?;
 
-    let theme = convert_theme(json_theme, legacy_theme)?;
+    for theme_path in Assets.list("themes/")? {
+        let (_, theme_name) = theme_path.split_once("themes/").unwrap();
 
-    println!("{:#?}", ThemePrinter::new(theme));
+        if theme_name == ".gitkeep" {
+            continue;
+        }
+
+        let (json_theme, legacy_theme) = load_theme(&theme_path)?;
+
+        let theme = convert_theme(json_theme, legacy_theme)?;
+
+        let theme_slug = theme.metadata.name.as_ref().to_case(Case::Snake);
+
+        let mut output_file = File::create(themes_path.join(format!("{theme_slug}.rs")))?;
+
+        let theme_module = format!("{:#?}", ThemePrinter::new(theme));
+
+        output_file.write_all(theme_module.as_bytes())?;
+
+        // println!("{:#?}", ThemePrinter::new(theme));
+    }
 
     Ok(())
 }
@@ -188,9 +211,9 @@ struct JsonSyntaxStyle {
 }
 
 /// Loads the [`Theme`] with the given name.
-fn load_theme(name: String) -> Result<(JsonTheme, LegacyTheme)> {
-    let theme_contents = Assets::get(&format!("themes/{name}.json"))
-        .with_context(|| format!("theme file not found: '{name}'"))?;
+fn load_theme(theme_path: &str) -> Result<(JsonTheme, LegacyTheme)> {
+    let theme_contents =
+        Assets::get(theme_path).with_context(|| format!("theme file not found: '{theme_path}'"))?;
 
     let json_theme: JsonTheme = serde_json::from_str(std::str::from_utf8(&theme_contents.data)?)
         .context("failed to parse legacy theme")?;