use clap::{crate_name, crate_version, Parser, Subcommand}; use dunce::canonicalize; use path_slash::PathExt; use std::fs; use std::fs::{write, OpenOptions}; use std::io::Write; use std::path::{Path, PathBuf}; use std::process::{exit, Command}; #[derive(Parser)] struct Cli { #[command(subcommand)] command: Cmd, } #[derive(Subcommand)] enum Cmd { /// Creates a new GSA project New { /// Name of new project name: String, /// Use local path to GSA instead of crates.io #[arg(long, short)] local: Option, /// Overwrite dir/file with name? WARNING: will delete stuff without further confirmation #[arg(long)] overwrite: bool, }, } fn main() { let cli = Cli::parse(); match cli.command { Cmd::New { name, local, overwrite, } => { println!("creating {}", name); let path = Path::new(&name); if path.exists() { if overwrite { if path.is_dir() { fs::remove_dir_all(path).unwrap(); } else { fs::remove_file(path).unwrap(); } } else { eprintln!( "aborting: file or directory {} already exists; use --overwrite if you want to delete it", name ); exit(1); } } if !Command::new("cargo") .arg("new") .arg(&name) .status() .unwrap() .success() { eprintln!("aborting: cargo new failed"); exit(1); } let mut cargo = OpenOptions::new() .write(true) .append(true) .open(path.join("Cargo.toml")) .expect("opening Cargo.toml failed"); match local { None => { writeln!(cargo, "{} = \"{}\"", crate_name!(), crate_version!()).unwrap(); } Some(local) => { writeln!( cargo, "{} = {{path = \"{}\"}}\nglam = \"0.24.0\"\n\n[profile.dev.package.{}]\nopt-level = 3", crate_name!(), canonicalize(local) .expect("couldn't find path") .to_slash_lossy(), crate_name!() ) .unwrap(); } } write( path.join("src/main.rs"), include_str!("../examples/hello_world/main.rs"), ) .unwrap(); write( path.join("src/gfx.gif"), include_bytes!("../examples/hello_world/gfx.gif"), ) .unwrap(); } } }