Start adding infrastructure to pay attention to actions

This commit is contained in:
greg 2019-06-01 22:17:20 -07:00
parent 176b286332
commit e12ff6f30b
2 changed files with 52 additions and 13 deletions

View File

@ -1,5 +1,7 @@
use super::Repl;
use colored::*;
pub type BoxedCommandFunction = Box<(fn(&mut Repl, &[&str]) -> Option<String>)>;
/// A CommandTree is either a `Terminal` or a `NonTerminal`. When command parsing reaches the first
@ -32,6 +34,12 @@ pub enum ReplAction {
QuitProgram
}
impl ReplAction {
fn get_function(&self) -> impl Fn(&mut Repl, &[&str]) -> Option<String> {
|_: &mut Repl, _: &[&str]| { None }
}
}
impl CommandTree {
pub fn nonterm_no_further_tab_completions(s: &str, help: Option<&str>) -> CommandTree {
CommandTree::NonTerminal {name: s.to_string(), help_msg: help.map(|x| x.to_string()), children: vec![], action: ReplAction::Null }
@ -41,6 +49,10 @@ impl CommandTree {
CommandTree::Terminal {name: s.to_string(), help_msg: help.map(|x| x.to_string()), function, children, action: ReplAction::Null }
}
pub fn terminal_act(s: &str, help: Option<&str>, children: Vec<CommandTree>, action: ReplAction) -> CommandTree {
CommandTree::Terminal {name: s.to_string(), help_msg: help.map(|x| x.to_string()), function: Box::new(|_,_| { None }), children, action}
}
pub fn nonterm(s: &str, help: Option<&str>, children: Vec<CommandTree>) -> CommandTree {
CommandTree::NonTerminal {
name: s.to_string(),
@ -50,17 +62,6 @@ impl CommandTree {
}
}
/*
pub fn nonterm_with_function(s: &str, help: Option<&str>, children: Vec<CommandTree>, func: BoxedCommandFunction) -> CommandTree {
CommandTree::NonTerminal {
name: s.to_string(),
help_msg: help.map(|x| x.to_string()),
children,
function: Some(func),
}
}
*/
pub fn get_cmd(&self) -> &str {
match self {
CommandTree::Terminal { name, .. } => name.as_str(),
@ -83,4 +84,38 @@ impl CommandTree {
Top(children) => children.iter().map(|x| x.get_cmd()).collect()
}
}
pub fn execute(&self, repl: &mut Repl, arguments: &Vec<&str>) -> Option<String> {
let mut dir_pointer: &CommandTree = self;
let mut idx = 0;
let res: Result<(ReplAction, usize), String> = loop {
match dir_pointer {
CommandTree::Top(subcommands) | CommandTree::NonTerminal { children: subcommands, .. } => {
let next_command = match arguments.get(idx) {
Some(cmd) => cmd,
None => break Err(format!("Command requires arguments"))
};
idx += 1;
match subcommands.iter().find(|sc| sc.get_cmd() == *next_command) {
Some(command_tree) => {
dir_pointer = command_tree;
},
None => break Err(format!("Command {} not found", next_command))
};
},
CommandTree::Terminal { action, .. } => {
break Ok((action.clone(), idx));
},
}
};
match res {
Ok((action, idx)) => {
let f = action.get_function();
f(repl, &arguments[idx..])
},
Err(err) => Some(err.red().to_string())
}
}
}

View File

@ -130,21 +130,25 @@ impl Repl {
fn handle_interpreter_directive(&mut self, input: &str) -> Option<String> {
let mut iter = input.chars();
iter.next();
let commands: Vec<&str> = iter
let arguments: Vec<&str> = iter
.as_str()
.split_whitespace()
.collect();
if commands.len() < 1 {
if arguments.len() < 1 {
return None;
}
let directives = self.get_directives();
directives.execute(self, &arguments)
/*
let result: Result<(&BoxedCommandFunction, _), String> = Repl::get_function_from_directives(&directives, &commands);
match result {
Ok((f, idx)) => f(self, &commands[idx..]),
Err(err) => Some(err.red().to_string())
}
*/
}
fn print_help_message(&mut self, commands_passed_to_help: &[&str] ) -> String {