use std::env::set_current_dir; use std::fs; use std::io::Write as _; use std::path::Path; use std::process::Command; use structopt::StructOpt; const TOSIN_DEPENDENCY: &str = concat!(r#"tosin = { path = ""#, env!("CARGO_MANIFEST_DIR"), r#"" }"#); const PROJECT_MAIN: &str = r#" use tosin::Settings; use tosin::contrib::admin; use tosin::urls::{UrlMap, url_map}; fn urls() -> UrlMap { url_map! { "admin" / ..admin::site::urls(), } } fn settings() -> Settings { Settings { ..Settings::default() } } tosin::main!(urls(), settings()); "#; const APP_MOD: &str = r#" pub mod urls; pub mod views; pub use urls::urls; "#; const APP_URLS: &str = r#" use tosin::urls::{UrlMap, url_map}; use super::views; pub fn urls() -> UrlMap { todo!("fill in URL map") } "#; const APP_VIEWS: &str = r#" use tosin::http::{Reply, Response}; todo!("write some views"); "#; #[derive(StructOpt, Debug)] enum Opt { /// Start a new project/site (can contain multiple apps) StartProject { name: Option, }, /// Start a new app StartApp { name: String, } } fn main() { let opts = Opt::from_args(); match opts { Opt::StartProject { name } => { match name { Some(name) => { // there's a name, so we're creating a project. // TODO make this all more robust let cargo_new = Command::new("cargo") .args(&["new", "--bin", &name]) .status() .unwrap(); if !cargo_new.success() { panic!("cargo new failed"); } set_current_dir(name).unwrap(); let mut cargo_toml = fs::OpenOptions::new() .append(true) .open("Cargo.toml") .unwrap(); writeln!(cargo_toml, "{}", TOSIN_DEPENDENCY).unwrap(); drop(cargo_toml); fs::write("src/main.rs", PROJECT_MAIN).unwrap(); } None => { todo!("absorb existing Rust project maybe??") } } } Opt::StartApp { name } => { // TODO make this more robust if fs::metadata("Cargo.toml").is_ok() { let app_folder = Path::new("src").join(name); fs::create_dir(&app_folder).unwrap(); fs::write(app_folder.join("mod.rs"), APP_MOD).unwrap(); fs::write(app_folder.join("urls.rs"), APP_URLS).unwrap(); fs::write(app_folder.join("views.rs"), APP_VIEWS).unwrap(); } else { todo!("new standalone app crate maybe??") } } } }