use std::fmt;
use std::collections::HashMap;
use super::{Argument, CommandExtension, CommandName, Context};
#[derive(Debug, PartialEq, Clone)]
pub enum Feedback {
RunNode(Context),
None,
}
pub trait Command {
fn args(&self) -> Vec<Argument>;
fn name(&self) -> CommandName;
fn about(&self) -> &str;
fn execute(
&self,
commands: &HashMap<CommandName, CollectedCommand>,
context: Context,
exts: &Fn(Context) -> Context,
) -> Feedback;
}
pub struct CollectedCommand {
command: Box<Command>,
args: Vec<Argument>,
exts: Vec<Box<CommandExtension>>,
}
impl CollectedCommand {
pub fn new(command: Box<Command>) -> CollectedCommand {
CollectedCommand {
args: command.args(),
command: command,
exts: Vec::new(),
}
}
pub fn args(&self) -> &Vec<Argument> {
&self.args
}
pub fn name(&self) -> CommandName {
self.command.name()
}
pub fn about(&self) -> &str {
self.command.about()
}
pub fn extend(&mut self, extender: Option<Box<CommandExtension>>) {
if let Some(extender) = extender {
let args = extender.args();
self.args.extend(args.into_iter());
self.exts.push(extender);
}
}
pub fn execute(
&self,
commands: &HashMap<CommandName, CollectedCommand>,
context: Context,
) -> Feedback {
self.command.execute(commands, context, &|context| {
let mut new_context = context.clone();
for ext in &self.exts {
new_context = ext.execute(new_context).expect(
"Could not execute extension.",
);
}
new_context
})
}
}
impl fmt::Debug for CollectedCommand {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"CollectedCommand {{ args: {:?}, ext_count: {} }}",
self.args,
self.exts.len()
)
}
}