use crate::spec::Specs;
use flaggy_values::error::{ValueError, ValueResult};
use flaggy_values::value::Values;
use std::fmt;
use std::iter::Peekable;
pub type CommandResult<E> = ::std::result::Result<(), E>;
pub type CommandCallback<'a, E> = Box<dyn FnMut(Values) -> CommandResult<E> + 'a>;
pub struct Command<'a, E> {
pub name: String,
pub help: String,
pub flags: Specs,
pub callback: CommandCallback<'a, E>,
}
impl<'a, E> Command<'a, E> {
pub fn new(name: &str, help: &str, flags: Specs, callback: CommandCallback<'a, E>) -> Self {
Command {
name: name.to_owned(),
help: help.to_owned(),
flags: flags,
callback: callback,
}
}
pub(crate) fn execute(&mut self, values: Values) -> CommandResult<E> {
self.callback.as_mut()(values)
}
}
impl<'a, E> fmt::Debug for Command<'a, E> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(
format!(
"Command {{ {:#?}, {:#?}, {:#?} }}",
self.name, self.help, self.flags
)
.as_str(),
)
}
}
impl<'a, E> PartialEq for Command<'a, E> {
fn eq(&self, other: &Self) -> bool {
self.name == other.name
}
}
pub(crate) fn parse_command<'a, 'b, I: Iterator<Item = &'a String>, E>(
args: &mut Peekable<I>,
commands: &Vec<Command<'b, E>>,
) -> ValueResult<usize> {
let idx = match args.next() {
None => return Err(ValueError::MissingCommand),
Some(command_arg) => match commands
.iter()
.position(|command| command.name == *command_arg)
{
None => return Err(ValueError::UnknownCommand(command_arg.to_owned())),
Some(idx) => idx,
},
};
Ok(idx)
}