use std::path::PathBuf;
use std::process::ExitCode;
use clap::{Parser, Subcommand};
use gpui_rhai_cli::{BundledRegistry, Project, ProjectError};
#[derive(Debug, Parser)]
#[command(name = "gpui-rhai", version, about)]
struct Cli {
#[arg(long, default_value = ".")]
root: PathBuf,
#[arg(long, global = true)]
dry_run: bool,
#[command(subcommand)]
command: Command,
}
#[derive(Debug, Subcommand)]
enum Command {
Init,
Add {
components: Vec<String>,
},
Check,
Dev,
Diff,
Update,
Embed,
Metadata,
ThemeStudio {
path: Option<PathBuf>,
},
Gallery {
#[arg(long)]
list: bool,
#[arg(long)]
story: Option<String>,
#[arg(long, default_value = "basic")]
case: String,
#[arg(long, default_value = "default-dark")]
theme: String,
#[arg(long, default_value = "en")]
locale: String,
#[arg(long, default_value = "normal")]
motion: String,
},
}
fn run(cli: Cli) -> Result<(), ProjectError> {
let registry = BundledRegistry::load()?;
let root = cli.root.clone();
let project = Project::new(cli.root);
match cli.command {
Command::Init => {
let plan = project.plan_init()?;
println!("{}", plan.summary());
if !cli.dry_run {
plan.apply()?;
}
}
Command::Add { components } => {
let plan = project.plan_add(®istry, &components)?;
println!("{}", plan.summary());
if !cli.dry_run {
plan.apply()?;
}
}
Command::Check => {
let report = project.check()?;
println!("{}", report.summary());
}
Command::Dev => project.dev()?,
Command::Diff => println!("{}", project.diff()?.join("\n")),
Command::Update => {
let plan = project.plan_update(®istry)?;
println!("{}", plan.summary());
let conflicts = plan.conflicts().to_vec();
if !cli.dry_run {
plan.apply()?;
}
if !conflicts.is_empty() {
return Err(ProjectError::UpdateConflictsWritten(conflicts));
}
}
Command::Embed => {
let plan = project.plan_embed()?;
println!("{}", plan.summary());
if !cli.dry_run {
plan.apply()?;
}
}
Command::Metadata => {
let plan = project.plan_editor_metadata()?;
println!("{}", plan.summary());
if !cli.dry_run {
plan.apply()?;
}
}
Command::ThemeStudio { path } => {
if cli.dry_run {
println!("would open Theme Studio");
} else {
gpui_rhai_cli::theme_studio::run(root, path).map_err(ProjectError::ThemeStudio)?;
}
}
Command::Gallery {
list,
story,
case,
theme,
locale,
motion,
} => {
if list {
println!("{}", gpui_rhai_cli::gallery::list_text());
} else if cli.dry_run {
println!("would open Gallery");
} else {
let motion = gpui_rhai_cli::gallery::parse_motion_preference(&motion)
.map_err(ProjectError::Gallery)?;
gpui_rhai_cli::gallery::run(&gpui_rhai_cli::gallery::GalleryLaunch {
story: story
.unwrap_or_else(|| gpui_rhai_cli::gallery::DEFAULT_STORY.to_owned()),
case,
theme,
locale,
motion,
})
.map_err(ProjectError::Gallery)?;
}
}
}
Ok(())
}
fn main() -> ExitCode {
let result = if std::env::var("GPUI_RHAI_GALLERY").is_ok_and(|value| value == "1") {
gpui_rhai_cli::gallery::run(&gpui_rhai_cli::gallery::GalleryLaunch {
story: std::env::var("GPUI_RHAI_GALLERY_STORY")
.unwrap_or_else(|_| gpui_rhai_cli::gallery::DEFAULT_STORY.to_owned()),
case: std::env::var("GPUI_RHAI_GALLERY_CASE").unwrap_or_else(|_| "basic".to_owned()),
theme: std::env::var("GPUI_RHAI_GALLERY_THEME")
.unwrap_or_else(|_| "default-dark".to_owned()),
locale: std::env::var("GPUI_RHAI_GALLERY_LOCALE").unwrap_or_else(|_| "en".to_owned()),
motion: gpui_rhai_cli::gallery::parse_motion_preference(
&std::env::var("GPUI_RHAI_GALLERY_MOTION").unwrap_or_else(|_| "normal".to_owned()),
)
.unwrap_or(gpui_rhai::MotionPreference::Normal),
})
.map_err(ProjectError::Gallery)
} else if std::env::var("GPUI_RHAI_THEME_STUDIO").is_ok_and(|value| value == "1") {
std::env::current_dir()
.map_err(|error| ProjectError::ThemeStudio(error.to_string()))
.and_then(|root| {
gpui_rhai_cli::theme_studio::run(root, None).map_err(ProjectError::ThemeStudio)
})
} else {
run(Cli::parse())
};
match result {
Ok(()) => ExitCode::SUCCESS,
Err(error) => {
eprintln!("gpui-rhai: {error}");
ExitCode::FAILURE
}
}
}