From e5bc0486b58f24dc4a1309e2e14f71bf72ad7248 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Thu, 30 Jan 2025 20:22:10 -0500 Subject: [PATCH] Add `schema_generator` for generating JSON schemas (#23991) This PR adds a `schema_generator` crate that can be used to generate our various JSON schemas for publishing elsewhere. Currently it does the simplest thing possible and just prints the JSON schema to stdout. We can make this a but more robust later. I also removed the schema-printing facilities from the `theme_importer`, as they don't really make sense there. Release Notes: - N/A --- Cargo.lock | 14 ++++++- Cargo.toml | 1 + crates/schema_generator/Cargo.toml | 18 +++++++++ crates/schema_generator/LICENSE-GPL | 1 + crates/schema_generator/src/main.rs | 26 +++++++++++++ crates/theme_importer/Cargo.toml | 1 - crates/theme_importer/src/main.rs | 59 ++++++++--------------------- 7 files changed, 75 insertions(+), 45 deletions(-) create mode 100644 crates/schema_generator/Cargo.toml create mode 120000 crates/schema_generator/LICENSE-GPL create mode 100644 crates/schema_generator/src/main.rs diff --git a/Cargo.lock b/Cargo.lock index f7a49645d1..e0ccab3a98 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11438,6 +11438,19 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "schema_generator" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "env_logger 0.11.6", + "schemars", + "serde", + "serde_json", + "theme", +] + [[package]] name = "schemars" version = "0.8.21" @@ -13278,7 +13291,6 @@ dependencies = [ "log", "palette", "rust-embed", - "schemars", "serde", "serde_json", "serde_json_lenient", diff --git a/Cargo.toml b/Cargo.toml index 727197b756..412da3b320 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -108,6 +108,7 @@ members = [ "crates/rich_text", "crates/rope", "crates/rpc", + "crates/schema_generator", "crates/search", "crates/semantic_index", "crates/semantic_version", diff --git a/crates/schema_generator/Cargo.toml b/crates/schema_generator/Cargo.toml new file mode 100644 index 0000000000..865f76f4af --- /dev/null +++ b/crates/schema_generator/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "schema_generator" +version = "0.1.0" +publish.workspace = true +edition.workspace = true +license = "GPL-3.0-or-later" + +[lints] +workspace = true + +[dependencies] +anyhow.workspace = true +clap = { workspace = true, features = ["derive"] } +env_logger.workspace = true +schemars = { workspace = true, features = ["indexmap2"] } +serde.workspace = true +serde_json.workspace = true +theme.workspace = true diff --git a/crates/schema_generator/LICENSE-GPL b/crates/schema_generator/LICENSE-GPL new file mode 120000 index 0000000000..89e542f750 --- /dev/null +++ b/crates/schema_generator/LICENSE-GPL @@ -0,0 +1 @@ +../../LICENSE-GPL \ No newline at end of file diff --git a/crates/schema_generator/src/main.rs b/crates/schema_generator/src/main.rs new file mode 100644 index 0000000000..2109dbd807 --- /dev/null +++ b/crates/schema_generator/src/main.rs @@ -0,0 +1,26 @@ +use anyhow::Result; +use clap::Parser; +use schemars::schema_for; +use theme::{IconThemeFamilyContent, ThemeFamilyContent}; + +#[derive(Parser, Debug)] +struct Args {} + +fn main() -> Result<()> { + env_logger::init(); + + let _args = Args::parse(); + + let theme_family_schema = schema_for!(ThemeFamilyContent); + println!("Theme Schema:"); + println!("{}", serde_json::to_string_pretty(&theme_family_schema)?); + + let icon_theme_family_schema = schema_for!(IconThemeFamilyContent); + println!("Icon Theme Schema:"); + println!( + "{}", + serde_json::to_string_pretty(&icon_theme_family_schema)? + ); + + Ok(()) +} diff --git a/crates/theme_importer/Cargo.toml b/crates/theme_importer/Cargo.toml index 1323b6345f..a78ca1d5ea 100644 --- a/crates/theme_importer/Cargo.toml +++ b/crates/theme_importer/Cargo.toml @@ -16,7 +16,6 @@ indexmap.workspace = true log.workspace = true palette.workspace = true rust-embed.workspace = true -schemars = { workspace = true, features = ["indexmap2"] } serde.workspace = true serde_json.workspace = true serde_json_lenient.workspace = true diff --git a/crates/theme_importer/src/main.rs b/crates/theme_importer/src/main.rs index d8e98b5d62..c2ceee4cfc 100644 --- a/crates/theme_importer/src/main.rs +++ b/crates/theme_importer/src/main.rs @@ -7,14 +7,13 @@ use std::io::Write; use std::path::PathBuf; use anyhow::{Context as _, Result}; -use clap::{Parser, Subcommand}; +use clap::Parser; use indexmap::IndexMap; use log::LevelFilter; -use schemars::schema_for; use serde::Deserialize; use simplelog::ColorChoice; use simplelog::{TermLogger, TerminalMode}; -use theme::{Appearance, AppearanceContent, ThemeFamilyContent}; +use theme::{Appearance, AppearanceContent}; use crate::vscode::VsCodeTheme; use crate::vscode::VsCodeThemeConverter; @@ -71,53 +70,25 @@ pub struct ThemeMetadata { #[derive(Parser)] #[command(author, version, about, long_about = None)] struct Args { - #[command(subcommand)] - command: Command, -} + /// The path to the theme to import. + theme_path: PathBuf, -#[derive(PartialEq, Subcommand)] -enum Command { - /// Prints the JSON schema for a theme. - PrintSchema, - /// Converts a VSCode theme to Zed format [default] - Convert { - /// The path to the theme to import. - theme_path: PathBuf, + /// Whether to warn when values are missing from the theme. + #[arg(long)] + warn_on_missing: bool, - /// Whether to warn when values are missing from the theme. - #[arg(long)] - warn_on_missing: bool, - - /// The path to write the output to. - #[arg(long, short)] - output: Option, - }, + /// The path to write the output to. + #[arg(long, short)] + output: Option, } fn main() -> Result<()> { let args = Args::parse(); - match args.command { - Command::PrintSchema => { - let theme_family_schema = schema_for!(ThemeFamilyContent); - println!( - "{}", - serde_json::to_string_pretty(&theme_family_schema).unwrap() - ); - Ok(()) - } - Command::Convert { - theme_path, - warn_on_missing, - output, - } => convert(theme_path, output, warn_on_missing), - } -} - -fn convert(theme_file_path: PathBuf, output: Option, warn_on_missing: bool) -> Result<()> { let log_config = { let mut config = simplelog::ConfigBuilder::new(); - if !warn_on_missing { + + if !args.warn_on_missing { config.add_filter_ignore_str("theme_printer"); } @@ -132,11 +103,13 @@ fn convert(theme_file_path: PathBuf, output: Option, warn_on_missing: b ) .expect("could not initialize logger"); + let theme_file_path = args.theme_path; + let theme_file = match File::open(&theme_file_path) { Ok(file) => file, Err(err) => { log::info!("Failed to open file at path: {:?}", theme_file_path); - return Err(err.into()); + return Err(err)?; } }; @@ -159,7 +132,7 @@ fn convert(theme_file_path: PathBuf, output: Option, warn_on_missing: b ); let theme_json = serde_json::to_string_pretty(&theme).unwrap(); - if let Some(output) = output { + if let Some(output) = args.output { let mut file = File::create(output)?; file.write_all(theme_json.as_bytes())?; } else {