use crate::Meta; use clap::{App, AppSettings, Arg, SubCommand}; pub struct AppState { pub meta: Meta, pub cmd: Command, } pub enum Command { Init, Generate, Install, Set(String, Option), } pub fn parse() -> AppState { let project_id = Arg::with_name("project id").help("The project identifier. Format: [client/]"); let timefile = Arg::with_name("timefile") .help("Location of the project's time file") .takes_value(true) .long("file") .short("f") .default_value("./time.cass"); let template = Arg::with_name("template") .help("Override the default application template") .long("templ") .short("t") .takes_value(true) .default_value("$XDG_CONFIG_HOME/k-office/template.tex"); let revision = Arg::with_name("revision") .help("Override the default revision system") .long("rev") .short("r") .takes_value(true); let app = App::new("invoice") .version(env!("CARGO_PKG_VERSION")) .about("A k-office tool to generate and manage invoices") .settings(&[ AppSettings::SubcommandRequired, AppSettings::GlobalVersion, AppSettings::DontCollapseArgsInUsage, ]) .subcommand( SubCommand::with_name("init") .about("Initialise a new invoice config") .arg(project_id.clone()) .arg(timefile) .arg(revision.clone()), ) .subcommand( SubCommand::with_name("generate") .about("Generate an invoice PDF for a client/ project based on a template") .arg(project_id) .arg(revision) .arg(template), ) .subcommand( SubCommand::with_name("set") .about("Set a variable in the k-office configuration") .arg( Arg::with_name("key") .required(true) .takes_value(true) .help("The configuration key to set"), ) .arg( Arg::with_name("value") .takes_value(true) .help("The value to set the key to. Missing value deletes the key"), ), ); let matches = app.get_matches(); let project_id = match matches.subcommand() { ("init", Some(vals)) => vals.value_of("project id"), ("generate", Some(vals)) => vals.value_of("project id"), _ => None, }; let timefile = match matches.subcommand() { ("init", Some(vals)) => vals.value_of("timefile"), ("generate", Some(vals)) => vals.value_of("timefile"), _ => None, }; let template = match matches.subcommand() { ("init", Some(vals)) => vals.value_of("template"), ("generate", Some(vals)) => vals.value_of("template"), _ => None, }; let revision = match matches.subcommand() { ("init", Some(vals)) => vals.value_of("revision"), ("generate", Some(vals)) => vals.value_of("revision"), _ => None, }; let (key, value) = match matches.subcommand() { ("set", Some(vals)) => (vals.value_of("key"), vals.value_of("value")), _ => (None, None), }; AppState { meta: crate::base::init(project_id, timefile, template, revision), cmd: match matches.subcommand() { ("init", _) => Command::Init, ("generate", _) => Command::Generate, ("set", _) => Command::Set(key.unwrap().into(), value.map(Into::into)), _ => unreachable!(), }, } }