use clap::{AppSettings, Parser, Subcommand};
use path_clean::PathClean;
use std::cell::RefCell;
use std::collections::HashMap;
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;
use crate::config::{CrateConfig, RswConfig};
use crate::core::{Build, Clean, Create, Init, Link, RswInfo, Watch};
use crate::utils::{init_rsw_crates, print, rsw_watch_file};
#[derive(Parser)]
#[clap(version, about, long_about = None)]
#[clap(global_setting(AppSettings::PropagateVersion))]
#[clap(global_setting(AppSettings::UseLongFormatForHelpSubcommand))]
pub struct Cli {
#[clap(subcommand)]
command: Commands,
}
#[derive(Subcommand)]
pub enum Commands {
Init,
Build,
Watch,
Clean,
New {
name: String,
#[clap(short = 't', long)]
template: Option<String>,
#[clap(short = 'm', long)]
mode: Option<String>,
},
}
impl Cli {
pub fn new() {
match &Cli::parse().command {
Commands::Init => Cli::rsw_init(),
Commands::Clean => Cli::rsw_clean(),
Commands::Build => {
Cli::rsw_build();
}
Commands::Watch => {
Cli::rsw_watch(Some(Arc::new(|a, b| {
let name = &a.name;
let path = &b.to_string_lossy().to_string();
let info_content = format!(
"[RSW::OK]\n[RSW::NAME] :~> {}\n[RSW::PATH] :~> {}",
name, path
);
rsw_watch_file(info_content.as_bytes(), "".as_bytes(), "info".into()).unwrap();
})));
}
Commands::New {
name,
template,
mode,
} => {
Cli::rsw_new(name, template, mode);
}
}
}
pub fn rsw_build() {
Cli::wp_build(Arc::new(Cli::parse_toml()), "build", true);
}
pub fn rsw_watch(
callback: Option<Arc<dyn Fn(&CrateConfig, std::path::PathBuf) + Send + Sync + 'static>>,
) {
let config = Arc::new(Cli::parse_toml());
Cli::wp_build(config.clone(), "watch", true);
Watch::new(config, callback.unwrap()).init();
}
pub fn rsw_init() {
Init::new().unwrap();
}
pub fn rsw_clean() {
Clean::new(Cli::parse_toml());
}
pub fn rsw_new(name: &String, template: &Option<String>, mode: &Option<String>) {
Create::new(
Cli::parse_toml().new.unwrap(),
name.into(),
template.to_owned(),
mode.to_owned(),
)
.init();
}
pub fn parse_toml() -> RswConfig {
let config = RswConfig::new().unwrap();
trace!("{:#?}", config);
let mut crates = Vec::new();
for i in &config.crates {
let name = &i.name;
let root = i.root.as_ref().unwrap();
let out = i.out_dir.as_ref().unwrap();
let crate_out = PathBuf::from(root).join(name).join(out);
crates.push(format!(
"{} :~> {}",
name,
crate_out.clean().to_string_lossy().to_string()
));
}
init_rsw_crates(crates.join("\n").as_bytes()).unwrap();
config
}
pub fn wp_build(config: Arc<RswConfig>, rsw_type: &str, is_link: bool) {
let crates_map = Rc::new(RefCell::new(HashMap::new()));
let cli = &config.cli.to_owned().unwrap_or_else(|| "npm".to_string());
let mut has_crates = false;
let mut is_exit = true;
for i in &config.crates {
let run_build = rsw_type == "build" && i.build.as_ref().unwrap().run.unwrap();
let run_watch = rsw_type == "watch" && i.watch.as_ref().unwrap().run.unwrap();
if run_build || run_watch {
is_exit = false;
if cli == "npm" && i.link.unwrap() {
has_crates = true;
let rsw_crate = i.clone();
let crate_path = PathBuf::from(rsw_crate.root.as_ref().unwrap())
.join(&i.name)
.join(rsw_crate.out_dir.unwrap());
crates_map.borrow_mut().insert(
rsw_crate.name.to_string(),
crate_path.to_string_lossy().to_string(),
);
}
Build::new(i.clone(), rsw_type, cli.into(), is_link).init();
}
}
if is_exit {
print(RswInfo::LoadCrate(rsw_type.into()));
std::process::exit(1);
}
let crates = crates_map.borrow();
if cli == "npm" && has_crates {
Link::npm_link(
cli.into(),
Vec::from_iter(crates.values().map(|i| i.into())),
);
}
}
}