use crate::{dispatch, paths, receipt};
use clap::{CommandFactory, FromArgMatches, Parser};
use std::path::Path;
#[derive(Parser)]
#[command(
name = "zr",
version,
about = "Module dispatcher",
disable_help_subcommand = true,
allow_external_subcommands = true,
)]
struct ZrCli {
#[arg(long, conflicts_with = "text")]
json: bool,
#[arg(long, conflicts_with = "json")]
text: bool,
#[command(subcommand)]
command: Option<ZrCommand>,
}
#[derive(clap::Subcommand)]
enum ZrCommand {
#[command(external_subcommand)]
Module(Vec<String>),
}
fn build_package_list_help(home: &Path) -> String {
let mut out = String::new();
if let Ok(packages) = receipt::list_all(home) {
let active: Vec<_> = packages.iter().filter(|(_, r)| r.active).collect();
if active.is_empty() {
out.push_str("No packages installed. Use `zacor install` to add packages.");
} else {
out.push_str("Available packages:");
for (name, r) in active {
out.push_str(&format!("\n {} v{}", name, r.current));
}
}
} else {
out.push_str("No packages installed. Use `zacor install` to add packages.");
}
out
}
pub fn run() -> i32 {
let home = match paths::zr_home() {
Ok(h) => h,
Err(e) => {
eprintln!("error: {:#}", e);
return 1;
}
};
if let Err(e) = paths::ensure_dirs(&home) {
eprintln!("error: {:#}", e);
return 1;
}
let package_list = build_package_list_help(&home);
let cli = match ZrCli::command()
.after_help(package_list)
.try_get_matches()
{
Ok(matches) => match ZrCli::from_arg_matches(&matches) {
Ok(cli) => cli,
Err(e) => {
eprintln!("{}", e);
return 1;
}
},
Err(e) => {
if e.use_stderr() {
eprintln!("{}", e);
return 1;
} else {
print!("{}", e);
return 0;
}
}
};
match cli.command {
Some(ZrCommand::Module(args)) => {
let module_name = &args[0];
let module_args: Vec<String> = args[1..].to_vec();
match dispatch::run(&home, module_name, &module_args, cli.json, cli.text) {
Ok(code) => code,
Err(e) => {
eprintln!("error: {:#}", e);
1
}
}
}
None => {
let package_list = build_package_list_help(&home);
let _ = ZrCli::command()
.after_help(package_list)
.print_help();
println!();
0
}
}
}