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
This commit is contained in:
Marshall Bowers 2025-01-30 20:22:10 -05:00 committed by GitHub
parent b6e54ae2f1
commit e5bc0486b5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 75 additions and 45 deletions

14
Cargo.lock generated
View file

@ -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",

View file

@ -108,6 +108,7 @@ members = [
"crates/rich_text",
"crates/rope",
"crates/rpc",
"crates/schema_generator",
"crates/search",
"crates/semantic_index",
"crates/semantic_version",

View file

@ -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

View file

@ -0,0 +1 @@
../../LICENSE-GPL

View file

@ -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(())
}

View file

@ -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

View file

@ -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,16 +70,6 @@ pub struct ThemeMetadata {
#[derive(Parser)]
#[command(author, version, about, long_about = None)]
struct Args {
#[command(subcommand)]
command: Command,
}
#[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,
@ -91,33 +80,15 @@ enum Command {
/// The path to write the output to.
#[arg(long, short)]
output: Option<PathBuf>,
},
}
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<PathBuf>, 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<PathBuf>, 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<PathBuf>, 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 {