arkham 0.1.0

A framework for CLI applications
Documentation
use crate::{
    context::Context,
    opt::{self, Opt},
    vox, App,
};

pub type Handler = fn(&App, &Context, &[String]);

#[derive(Clone)]
pub struct Command {
    pub name: String,
    pub commands: Vec<Command>,
    pub handler: Option<Handler>,
    pub opts: Vec<opt::Opt>,
    pub long_desc: Option<String>,
    pub short_desc: Option<String>,
}

impl Command {
    pub fn new<T: Into<String>>(name: T) -> Self {
        Command {
            name: name.into(),
            commands: vec![],
            handler: None,
            opts: vec![],
            long_desc: None,
            short_desc: None,
        }
    }

    pub fn handler(mut self, f: Handler) -> Self {
        self.handler = Some(f);
        self
    }

    pub fn opt(mut self, opt: Opt) -> Self {
        self.opts.push(opt);
        self
    }

    pub fn short_desc(mut self, short_desc: &str) -> Self {
        self.short_desc = Some(short_desc.into());
        self
    }

    pub fn long_desc(mut self, long_desc: &str) -> Self {
        self.short_desc = Some(long_desc.into());
        self
    }
}

pub(crate) fn help(app: &App, _ctx: &Context, args: &[String]) {
    vox::print(app.application_header());
    print_command_help(&app.root, args);
}

pub(crate) fn print_command_help(cmd: &Command, args: &[String]) {
    if !args.is_empty() {
        if let Some(cmd) = cmd.commands.iter().find(|c| Some(&c.name) == args.first()) {
            return print_command_help(cmd, &args[1..]);
        }
    }
    vox::print("");
    if let Some(desc) = cmd.long_desc.as_ref().or(cmd.short_desc.as_ref()) {
        if cmd.name != "root" {
            vox::header(&cmd.name.to_uppercase());
        }
        vox::print(desc);
        vox::print("");
    }
    if !cmd.opts.is_empty() {
        vox::header("OPTIONS");
        vox::description_list(
            cmd.opts
                .iter()
                .map(|o| (o.usage(), o.desc.clone().unwrap_or_default()))
                .collect(),
        )
    }

    if !cmd.commands.is_empty() {
        vox::header("Subcommands");
        vox::description_list(
            cmd.commands
                .iter()
                .map(|c| (c.name.clone(), c.short_desc.clone().unwrap_or_default()))
                .collect(),
        )
    }
}