diff --git a/cli/src/bin/bs.rs b/cli/src/bin/bs.rs index 5225c76..fc118dc 100644 --- a/cli/src/bin/bs.rs +++ b/cli/src/bin/bs.rs @@ -81,26 +81,30 @@ async fn main() -> Result<(), Error> { .with_file(true) .without_time() .try_init() - .map_err(bs_cli::Error::Log)?; + .map_err(Error::Log)?; // load the config let config = Config::from_path(opt.config, opt.keyfile, opt.sshagent, opt.sshagentenv)?; - let ret = match opt.cmd { - Some(cmd) => match cmd { + let command_reader: Box> = match opt.cmd { + Some(command) => Box::new(std::iter::once(command)), + None => Box::new(repl::ReplHelper::read()), + }; + + for command in command_reader { + let ret = match command { // process a config command Command::Config { cmd } => subcmds::config::go(cmd, &config).await, // process a plog command - Command::Plog { cmd } => subcmds::plog::go(*cmd, &config).await, - }, - None => repl::ReplHelper::run().await, - }; + Command::Plog { cmd } => plog::go(*cmd, &config).await, + }; - if let Err(ref e) = ret { - eprintln!("{}", e); - Opt::clap().print_help().unwrap(); - println!(); - ret? + if let Err(ref e) = ret { + eprintln!("{}", e); + Opt::clap().print_help().unwrap(); + println!(); + ret? + } } // save any config changes diff --git a/cli/src/repl.rs b/cli/src/repl.rs index d85fba2..e9e2369 100644 --- a/cli/src/repl.rs +++ b/cli/src/repl.rs @@ -1,12 +1,13 @@ use crate::{ subcmds::{config, plog}, - Command, Error, + Command, }; use colored::Colorize; use rustyline::{ completion::{Completer, FilenameCompleter, Pair}, highlight::{CmdKind, Highlighter, MatchingBracketHighlighter}, hint::{Hint, Hinter}, + history::DefaultHistory, validate::MatchingBracketValidator, Completer, Context, Helper, Validator, }; @@ -404,7 +405,7 @@ impl Default for ReplHelper { impl ReplHelper { /// Run the REPL - pub async fn run() -> Result<(), Error> { + pub fn read() -> ReplHelperIterator { let config = rustyline::Config::builder() .history_ignore_space(true) .completion_type(rustyline::CompletionType::List) @@ -416,14 +417,29 @@ impl ReplHelper { rl.set_helper(Some(h)); rl.helper_mut().expect("to get helper").colored_prompt = "bs>".green().to_string(); - let mut input; - Self::help(); + help(); + ReplHelperIterator { rl } + } +} + +/// An iterator for the REPL that yields commands +/// as long as the user doesn't quit +pub struct ReplHelperIterator { + rl: rustyline::Editor, +} + +impl Iterator for ReplHelperIterator { + type Item = Command; + fn next(&mut self) -> Option { + let mut input; loop { - let readline = rl.readline("bs> "); + let readline = self.rl.readline("bs> "); match readline { Ok(line) => { - rl.add_history_entry(line.as_str())?; + self.rl + .add_history_entry(line.as_str()) + .expect("to add history"); input = line; } Err(rustyline::error::ReadlineError::Interrupted) => { @@ -443,7 +459,9 @@ impl ReplHelper { if input.is_empty() { continue; } - rl.add_history_entry(input.as_str())?; + self.rl + .add_history_entry(input.as_str()) + .expect("to add history"); let mut parser = Parser::new(&input); parser.skip_ws(); match parser.simple_value() { @@ -451,14 +469,14 @@ impl ReplHelper { Ok(word) => match word.as_str() { "config" | "plog" => match Parser::parse_command(&input) { Ok(command) => { - println!("Parsed command: {:?}", command); + return Some(command); } Err(err) => { eprintln!("Error parsing command: {}", err); } }, "help" => { - Self::help(); + help(); } "quit" => { break; @@ -467,29 +485,7 @@ impl ReplHelper { }, } } - Ok(()) - } - - fn help() { - println!( - r#"Commands: -config [parameters] -plot [parameters] -help -quit - -Config Subcommands: -open - -Plog Subcommands: -close -fork -merge -open [key-op=STRING_COMMA_SEPARATED_LIST] [string-op=STRING_COMMA_SEPARATED_LIST] [file-op=STRING_COMMA_SEPARATED_LIST] [vlad=STRING] [pub-key=STRING] [entry-key=STRING] [lock=PATH_TO_SCRIPT] [unlock=PATH_TO_SCRIPT] [output=PATH_TO_FILE] -print [input=PATH_TO_FILE] -update [key-op=STRING_COMMA_SEPARATED_LIST] [string-op=STRING_COMMA_SEPARATED_LIST] [file-op=STRING_COMMA_SEPARATED_LIST] [delete-op=STRING_COMMA_SEPARATED_LIST] [entry-signing-key=PATH_TO_FILE] [input=PATH_TO_FILE] [lock=PATH_TO_SCRIPT] [unlock=PATH_TO_SCRIPT] [output=PATH_TO_FILE] -"# - ) + None } } @@ -636,3 +632,25 @@ impl CommandHint { } } } + +fn help() { + println!( + r#"Commands: +config [parameters] +plot [parameters] +help +quit + +Config Subcommands: +open + +Plog Subcommands: +close +fork +merge +open [key-op=STRING_COMMA_SEPARATED_LIST] [string-op=STRING_COMMA_SEPARATED_LIST] [file-op=STRING_COMMA_SEPARATED_LIST] [vlad=STRING] [pub-key=STRING] [entry-key=STRING] [lock=PATH_TO_SCRIPT] [unlock=PATH_TO_SCRIPT] [output=PATH_TO_FILE] +print [input=PATH_TO_FILE] +update [key-op=STRING_COMMA_SEPARATED_LIST] [string-op=STRING_COMMA_SEPARATED_LIST] [file-op=STRING_COMMA_SEPARATED_LIST] [delete-op=STRING_COMMA_SEPARATED_LIST] [entry-signing-key=PATH_TO_FILE] [input=PATH_TO_FILE] [lock=PATH_TO_SCRIPT] [unlock=PATH_TO_SCRIPT] [output=PATH_TO_FILE] +"# + ) +}