use super::{BaseCommand, Command};
use crate::command_set::CommandSet;
use crate::error::ShiError;
use crate::Result;
pub struct ParentCommand<'a, S> {
name: &'a str,
help: &'a str,
sub_cmds: CommandSet<'a, S>,
}
impl<'a, S> ParentCommand<'a, S> {
pub fn new(name: &'a str, sub_cmds: Vec<Command<'a, S>>) -> ParentCommand<'a, S> {
let mut command_set = CommandSet::new();
for sub_cmd in sub_cmds {
command_set.add(sub_cmd);
}
ParentCommand {
name,
help: "",
sub_cmds: command_set,
}
}
pub fn new_with_help(
name: &'a str,
help: &'a str,
sub_cmds: Vec<Command<'a, S>>,
) -> ParentCommand<'a, S> {
let mut command_set = CommandSet::new();
for sub_cmd in sub_cmds {
command_set.add(sub_cmd);
}
ParentCommand {
name,
help,
sub_cmds: command_set,
}
}
fn get_sub_cmd_for_args(&self, args: &[String]) -> Result<&Command<S>> {
let first_arg = match args.get(0) {
Some(arg) => arg,
None => return Err(ShiError::NoArgs),
};
match self.sub_cmds.get(first_arg) {
Some(cmd) => Ok(cmd),
None => {
return Err(ShiError::InvalidSubCommand {
got: first_arg.to_string(),
expected: self
.sub_commands()
.iter()
.map(|cmd| cmd.name().to_string())
.collect::<Vec<String>>(),
})
}
}
}
pub fn sub_commands(&self) -> &CommandSet<S> {
&self.sub_cmds
}
}
impl<'a, S> BaseCommand for ParentCommand<'a, S> {
type State = S;
fn name(&self) -> &str {
self.name
}
fn validate_args(&self, args: &[String]) -> Result<()> {
if let Some(first_arg) = args.first() {
if self.sub_commands().len() == 0 {
return Err(ShiError::InvalidSubCommand {
got: first_arg.clone(),
expected: args.to_vec(),
});
} else {
self.get_sub_cmd_for_args(args)?;
}
} else {
if self.sub_commands().len() != 0 {
return Err(ShiError::NoArgs);
}
}
Ok(())
}
fn execute(&self, state: &mut S, args: &[String]) -> Result<String> {
let sub_cmd = self.get_sub_cmd_for_args(args)?;
sub_cmd.execute(state, &args[1..].to_vec())
}
fn help(&self) -> String {
self.help.to_string()
}
}