use std::path::Path;
use jimtcl::{Interp, JimError, JimObject, JimResult};
use usage::{
Parser, Spec,
parse::{ParseOutput, ParseValue},
};
pub fn parse_args(interp: &Interp, script: &Path, args: &[String]) -> JimResult<()> {
let spec = Spec::parse_script(script).map_err(JimError::wrap)?;
let parsed = Parser::new(&spec).parse(args);
match parsed {
Err(e) => {
eprintln!("{}", e);
Err(JimError::from("command line parse failed"))
}
Ok(args) => add_args(interp, &args),
}
}
fn add_args(interp: &Interp, args: &ParseOutput) -> JimResult<()> {
let usage = JimObject::empty(interp);
for (flag, val) in &args.flags {
add_arg(interp, &usage, &flag.name, val)?;
}
for (arg, val) in &args.args {
add_arg(interp, &usage, &arg.name, val)?;
}
for (_, spec) in &args.available_flags {
if spec.arg.is_none() && !usage.dict_exists(&spec.name)? {
usage.dict_set(&spec.name, 0)?;
}
}
interp.set_variable("usage", usage)?;
Ok(())
}
fn add_arg<'jim>(
interp: &'jim Interp,
usage: &JimObject<'jim>,
name: &str,
value: &ParseValue,
) -> JimResult<()> {
match value {
ParseValue::String(s) => usage.dict_set(name, s.as_str())?,
ParseValue::Bool(true) => usage.dict_set(name, "yes")?,
ParseValue::Bool(false) => usage.dict_set(name, "no")?,
ParseValue::MultiBool(bools) => {
let n = bools.iter().filter(|b| **b).count();
usage.dict_set(name, n)?;
}
ParseValue::MultiString(strings) => {
let val = JimObject::empty(interp);
for v in strings {
val.list_append(v.as_str());
}
usage.dict_set_obj(interp.new_string(name), val)?;
}
}
Ok(())
}