use std::fmt;
use crate::arg::{Arg, ArgKind};
use crate::matches::Matches;
type Handler = Box<dyn Fn(&Matches)>;
pub struct Command {
pub(crate) name: String,
pub(crate) aliases: Vec<String>,
pub(crate) about: Option<String>,
pub(crate) args: Vec<Arg>,
pub(crate) subcommands: Vec<Command>,
pub(crate) hidden: bool,
pub(crate) requires_auth: bool,
pub(crate) handler: Option<Handler>,
}
impl Command {
#[must_use]
pub fn new(name: impl Into<String>) -> Command {
Command {
name: name.into(),
aliases: Vec::new(),
about: None,
args: Vec::new(),
subcommands: Vec::new(),
hidden: false,
requires_auth: false,
handler: None,
}
}
#[must_use]
pub fn alias(mut self, alias: impl Into<String>) -> Command {
self.aliases.push(alias.into());
self
}
#[must_use]
pub fn aliases<I, S>(mut self, aliases: I) -> Command
where
I: IntoIterator<Item = S>,
S: Into<String>,
{
self.aliases.extend(aliases.into_iter().map(Into::into));
self
}
#[must_use]
pub fn about(mut self, text: impl Into<String>) -> Command {
self.about = Some(text.into());
self
}
#[must_use]
pub fn arg(mut self, arg: Arg) -> Command {
self.args.push(arg);
self
}
#[must_use]
pub fn subcommand(mut self, cmd: Command) -> Command {
self.subcommands.push(cmd);
self
}
#[must_use]
pub fn hidden(mut self, yes: bool) -> Command {
self.hidden = yes;
self
}
#[must_use]
pub fn requires_auth(mut self, yes: bool) -> Command {
self.requires_auth = yes;
self
}
#[must_use]
pub fn run(mut self, handler: impl Fn(&Matches) + 'static) -> Command {
self.handler = Some(Box::new(handler));
self
}
pub(crate) fn find_long(&self, long: &str) -> Option<&Arg> {
self.args.iter().find(|a| a.long_name() == Some(long))
}
pub(crate) fn find_short(&self, short: char) -> Option<&Arg> {
self.args.iter().find(|a| a.short == Some(short))
}
pub(crate) fn matches_name(&self, name: &str) -> bool {
self.name == name || self.aliases.iter().any(|a| a == name)
}
pub(crate) fn find_subcommand(&self, name: &str) -> Option<&Command> {
self.subcommands.iter().find(|c| c.matches_name(name))
}
pub(crate) fn positionals(&self) -> impl Iterator<Item = &Arg> {
self.args.iter().filter(|a| a.kind == ArgKind::Positional)
}
}
impl fmt::Debug for Command {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("Command")
.field("name", &self.name)
.field("aliases", &self.aliases)
.field("about", &self.about)
.field("args", &self.args)
.field("subcommands", &self.subcommands)
.field("hidden", &self.hidden)
.field("requires_auth", &self.requires_auth)
.field("has_handler", &self.handler.is_some())
.finish()
}
}