assets/themes/src/vsc/ayu/LICENSE → assets/themes/src/vscode/ayu/LICENSE 🔗
Marshall Bowers created
assets/themes/src/vscode/ayu/LICENSE | 0
assets/themes/src/vscode/ayu/ayu-dark.json | 0
assets/themes/src/vscode/ayu/ayu-light.json | 0
assets/themes/src/vscode/ayu/ayu-mirage.json | 0
assets/themes/src/vscode/ayu/family.json | 0
assets/themes/src/vscode/dracula/LICENSE | 0
assets/themes/src/vscode/dracula/dracula.json | 0
assets/themes/src/vscode/dracula/family.json | 0
crates/theme2/src/theme2.rs | 3
crates/theme_importer/src/main.rs | 112 +++++++++++++-------
crates/theme_importer/src/vscode.rs | 72 ++++++------
11 files changed, 110 insertions(+), 77 deletions(-)
@@ -49,8 +49,7 @@ pub struct ThemeFamily {
impl ThemeFamily {}
pub struct ThemeVariant {
- #[allow(dead_code)]
- pub(crate) id: String,
+ pub id: String,
pub name: SharedString,
pub appearance: Appearance,
pub styles: ThemeStyles,
@@ -1,15 +1,21 @@
+use std::borrow::Cow;
+use std::fs::{self, File};
use std::path::PathBuf;
use std::str::FromStr;
-use std::{borrow::Cow, fs::File};
use anyhow::{anyhow, Context, Result};
use convert_case::Case;
-use gpui::{AssetSource, SharedString};
+use gpui::{serde_json, AssetSource, SharedString};
use log::LevelFilter;
use rust_embed::RustEmbed;
use serde::Deserialize;
use simplelog::SimpleLogger;
-use theme::{default_color_scales, ThemeColorsRefinement, ThemeFamily};
+use theme::{
+ default_color_scales, Appearance, GitStatusColors, PlayerColors, StatusColors, SyntaxTheme,
+ SystemColors, ThemeColors, ThemeColorsRefinement, ThemeFamily, ThemeStyles, ThemeVariant,
+};
+
+use crate::vscode::VsCodeTheme;
mod vscode;
@@ -23,20 +29,21 @@ pub(crate) fn new_theme_family(name: String, author: String) -> ThemeFamily {
}
}
-#[derive(Deserialize)]
+#[derive(Debug, Deserialize)]
struct FamilyJson {
pub name: String,
+ pub author: String,
pub themes: Vec<ThemeVariantJson>,
}
-#[derive(Deserialize)]
+#[derive(Debug, Deserialize)]
#[serde(rename_all = "snake_case")]
enum ThemeAppearanceJson {
Light,
Dark,
}
-#[derive(Deserialize)]
+#[derive(Debug, Deserialize)]
struct ThemeVariantJson {
pub name: String,
pub appearance: ThemeAppearanceJson,
@@ -69,54 +76,79 @@ fn main() -> Result<()> {
let themes_path = PathBuf::from_str("crates/theme2/src/themes")?;
- let mut theme_modules = Vec::new();
+ let vscode_themes_path = PathBuf::from_str("assets/themes/src/vscode/")?;
- for theme_path in Assets.list("themes/src/vsc/")? {
- let (_, theme_name) = theme_path.split_once("themes/").unwrap();
+ let mut theme_families = Vec::new();
- if theme_name == ".gitkeep" {
- continue;
- }
+ for theme_family_dir in fs::read_dir(&vscode_themes_path)? {
+ let theme_family_dir = theme_family_dir?;
- let theme_contents = Assets::get(&theme_path)
- .with_context(|| format!("theme file not found: '{theme_path}'"))?;
+ let theme_family_slug = theme_family_dir
+ .path()
+ .file_stem()
+ .ok_or(anyhow!("no file stem"))
+ .map(|stem| stem.to_string_lossy().to_string())?;
- // let json_theme: JsonTheme =
- // serde_json::from_str(std::str::from_utf8(&theme_contents.data)?)
- // .context("failed to parse legacy theme")?;
+ let family_metadata_file = File::open(theme_family_dir.path().join("family.json"))
+ .context(format!("no `family.json` found for '{theme_family_slug}'"))?;
- // let (json_theme, legacy_theme) = load_theme(&theme_path)?;
+ let family_metadata: FamilyJson = serde_json::from_reader(family_metadata_file).context(
+ format!("failed to parse `family.json` for '{theme_family_slug}'"),
+ )?;
- // let theme = convert_theme(json_theme, legacy_theme)?;
+ let mut themes = Vec::new();
- // let theme_slug = theme
- // .metadata
- // .name
- // .as_ref()
- // .replace("é", "e")
- // .to_case(Case::Snake);
+ for theme_entry in fs::read_dir(vscode_themes_path.join(theme_family_slug))? {
+ let theme_entry = theme_entry?;
- // let mut output_file = File::create(themes_path.join(format!("{theme_slug}.rs")))?;
+ let theme_file_path = theme_entry.path();
- // let theme_module = format!(
- // r#"
- // use gpui2::rgba;
+ let file_name = theme_file_path
+ .file_name()
+ .ok_or(anyhow!("no file stem"))
+ .map(|file_name| file_name.to_string_lossy())?;
- // use crate::{{PlayerTheme, SyntaxTheme, Theme, ThemeMetadata}};
+ if !file_name.ends_with(".json") {
+ continue;
+ }
- // pub fn {theme_slug}() -> Theme {{
- // {theme_definition}
- // }}
- // "#,
- // theme_definition = format!("{:#?}", ThemePrinter::new(theme))
- // );
+ if file_name == "family.json" {
+ continue;
+ }
- // output_file.write_all(theme_module.as_bytes())?;
+ let theme_file = File::open(&theme_file_path)?;
- theme_modules.push(theme_slug);
- }
+ let theme: VsCodeTheme = serde_json::from_reader(theme_file)
+ .context(format!("failed to parse theme {theme_file_path:?}"))?;
- println!("Hello, world!");
+ themes.push(theme);
+ }
+
+ let theme_family = ThemeFamily {
+ id: uuid::Uuid::new_v4().to_string(),
+ name: family_metadata.name.into(),
+ author: family_metadata.author.into(),
+ themes: themes
+ .into_iter()
+ .map(|theme| ThemeVariant {
+ id: uuid::Uuid::new_v4().to_string(),
+ name: "".into(),
+ appearance: Appearance::Dark,
+ styles: ThemeStyles {
+ system: SystemColors::default(),
+ colors: ThemeColors::default_dark(),
+ status: StatusColors::default(),
+ git: GitStatusColors::default(),
+ player: PlayerColors::default(),
+ syntax: SyntaxTheme::default_dark(),
+ },
+ })
+ .collect(),
+ scales: default_color_scales(),
+ };
+
+ theme_families.push(theme_family);
+ }
Ok(())
}
@@ -5,21 +5,21 @@ use serde::Deserialize;
use theme::{default_color_scales, ColorScales, ThemeFamily};
#[derive(Deserialize, Debug)]
-pub struct VSCodeTheme {
+pub struct VsCodeTheme {
#[serde(rename = "$schema")]
- pub schema: String,
- pub name: String,
- pub author: String,
- pub maintainers: Vec<String>,
+ pub schema: Option<String>,
+ pub name: Option<String>,
+ pub author: Option<String>,
+ pub maintainers: Option<Vec<String>>,
#[serde(rename = "semanticClass")]
- pub semantic_class: String,
+ pub semantic_class: Option<String>,
#[serde(rename = "semanticHighlighting")]
- pub semantic_highlighting: bool,
- pub colors: VSCodeColors,
+ pub semantic_highlighting: Option<bool>,
+ pub colors: VsCodeColors,
}
#[derive(Debug, Deserialize)]
-pub struct VSCodeColors {
+pub struct VsCodeColors {
#[serde(rename = "editor.foreground")]
text: String,
#[serde(rename = "editor.background")]
@@ -27,36 +27,38 @@ pub struct VSCodeColors {
}
pub(crate) fn new_theme_family_from_vsc(path: &Path) -> Result<ThemeFamily> {
- let path_str = path.to_str().unwrap();
- let family_name = path_str.split('/').last().unwrap();
+ todo!()
- let mut json_files: Vec<String> = Vec::new();
+ // let path_str = path.to_str().unwrap();
+ // let family_name = path_str.split('/').last().unwrap();
- if path.is_dir() {
- for entry in std::fs::read_dir(path).unwrap() {
- let entry = entry.unwrap();
- let path = entry.path();
- if path.is_file() {
- if let Some(extension) = path.extension() {
- if extension == "json" {
- json_files.push(path.file_name().unwrap().to_str().unwrap().to_string());
- }
- }
- }
- }
- } else {
- anyhow::bail!("Path is not a directory");
- }
+ // let mut json_files: Vec<String> = Vec::new();
+
+ // if path.is_dir() {
+ // for entry in std::fs::read_dir(path).unwrap() {
+ // let entry = entry.unwrap();
+ // let path = entry.path();
+ // if path.is_file() {
+ // if let Some(extension) = path.extension() {
+ // if extension == "json" {
+ // json_files.push(path.file_name().unwrap().to_str().unwrap().to_string());
+ // }
+ // }
+ // }
+ // }
+ // } else {
+ // anyhow::bail!("Path is not a directory");
+ // }
- let mut theme_family = ThemeFamily {
- id: uuid::Uuid::new_v4().to_string(),
- name: family_name.into(),
- author: "New Theme Family".into(),
- themes: Vec::new(),
- scales: default_color_scales(),
- };
+ // let mut theme_family = ThemeFamily {
+ // id: uuid::Uuid::new_v4().to_string(),
+ // name: family_name.into(),
+ // author: "New Theme Family".into(),
+ // themes: Vec::new(),
+ // scales: default_color_scales(),
+ // };
- Ok(theme_family)
+ // Ok(theme_family)
}
#[cfg(test)]