Start adding infrastructure to pay attention to actions
This commit is contained in:
parent
176b286332
commit
e12ff6f30b
@ -1,5 +1,7 @@
|
|||||||
use super::Repl;
|
use super::Repl;
|
||||||
|
|
||||||
|
use colored::*;
|
||||||
|
|
||||||
pub type BoxedCommandFunction = Box<(fn(&mut Repl, &[&str]) -> Option<String>)>;
|
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
|
/// A CommandTree is either a `Terminal` or a `NonTerminal`. When command parsing reaches the first
|
||||||
@ -32,6 +34,12 @@ pub enum ReplAction {
|
|||||||
QuitProgram
|
QuitProgram
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl ReplAction {
|
||||||
|
fn get_function(&self) -> impl Fn(&mut Repl, &[&str]) -> Option<String> {
|
||||||
|
|_: &mut Repl, _: &[&str]| { None }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl CommandTree {
|
impl CommandTree {
|
||||||
pub fn nonterm_no_further_tab_completions(s: &str, help: Option<&str>) -> 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 }
|
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 }
|
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 {
|
pub fn nonterm(s: &str, help: Option<&str>, children: Vec<CommandTree>) -> CommandTree {
|
||||||
CommandTree::NonTerminal {
|
CommandTree::NonTerminal {
|
||||||
name: s.to_string(),
|
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 {
|
pub fn get_cmd(&self) -> &str {
|
||||||
match self {
|
match self {
|
||||||
CommandTree::Terminal { name, .. } => name.as_str(),
|
CommandTree::Terminal { name, .. } => name.as_str(),
|
||||||
@ -83,4 +84,38 @@ impl CommandTree {
|
|||||||
Top(children) => children.iter().map(|x| x.get_cmd()).collect()
|
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())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -130,21 +130,25 @@ impl Repl {
|
|||||||
fn handle_interpreter_directive(&mut self, input: &str) -> Option<String> {
|
fn handle_interpreter_directive(&mut self, input: &str) -> Option<String> {
|
||||||
let mut iter = input.chars();
|
let mut iter = input.chars();
|
||||||
iter.next();
|
iter.next();
|
||||||
let commands: Vec<&str> = iter
|
let arguments: Vec<&str> = iter
|
||||||
.as_str()
|
.as_str()
|
||||||
.split_whitespace()
|
.split_whitespace()
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
if commands.len() < 1 {
|
if arguments.len() < 1 {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
let directives = self.get_directives();
|
let directives = self.get_directives();
|
||||||
|
directives.execute(self, &arguments)
|
||||||
|
|
||||||
|
/*
|
||||||
let result: Result<(&BoxedCommandFunction, _), String> = Repl::get_function_from_directives(&directives, &commands);
|
let result: Result<(&BoxedCommandFunction, _), String> = Repl::get_function_from_directives(&directives, &commands);
|
||||||
match result {
|
match result {
|
||||||
Ok((f, idx)) => f(self, &commands[idx..]),
|
Ok((f, idx)) => f(self, &commands[idx..]),
|
||||||
Err(err) => Some(err.red().to_string())
|
Err(err) => Some(err.red().to_string())
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
fn print_help_message(&mut self, commands_passed_to_help: &[&str] ) -> String {
|
fn print_help_message(&mut self, commands_passed_to_help: &[&str] ) -> String {
|
||||||
|
Loading…
Reference in New Issue
Block a user