diff options
Diffstat (limited to 'examples/repl.rs')
-rw-r--r-- | examples/repl.rs | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/examples/repl.rs b/examples/repl.rs new file mode 100644 index 0000000..c509ade --- /dev/null +++ b/examples/repl.rs @@ -0,0 +1,92 @@ +use std::io::Write; + +use clap::Command; + +fn main() -> Result<(), String> { + loop { + let line = readline()?; + let line = line.trim(); + if line.is_empty() { + continue; + } + + match respond(line) { + Ok(quit) => { + if quit { + break; + } + } + Err(err) => { + write!(std::io::stdout(), "{}", err).map_err(|e| e.to_string())?; + std::io::stdout().flush().map_err(|e| e.to_string())?; + } + } + } + + Ok(()) +} + +fn respond(line: &str) -> Result<bool, String> { + let args = shlex::split(line).ok_or("error: Invalid quoting")?; + let matches = cli() + .try_get_matches_from(&args) + .map_err(|e| e.to_string())?; + match matches.subcommand() { + Some(("ping", _matches)) => { + write!(std::io::stdout(), "Pong").map_err(|e| e.to_string())?; + std::io::stdout().flush().map_err(|e| e.to_string())?; + } + Some(("quit", _matches)) => { + write!(std::io::stdout(), "Exiting ...").map_err(|e| e.to_string())?; + std::io::stdout().flush().map_err(|e| e.to_string())?; + return Ok(true); + } + Some((name, _matches)) => unimplemented!("{}", name), + None => unreachable!("subcommand required"), + } + + Ok(false) +} + +fn cli() -> Command<'static> { + // strip out usage + const PARSER_TEMPLATE: &str = "\ + {all-args} + "; + // strip out name/version + const APPLET_TEMPLATE: &str = "\ + {about-with-newline}\n\ + {usage-heading}\n {usage}\n\ + \n\ + {all-args}{after-help}\ + "; + + Command::new("repl") + .multicall(true) + .arg_required_else_help(true) + .subcommand_required(true) + .subcommand_value_name("APPLET") + .subcommand_help_heading("APPLETS") + .help_template(PARSER_TEMPLATE) + .subcommand( + Command::new("ping") + .about("Get a response") + .help_template(APPLET_TEMPLATE), + ) + .subcommand( + Command::new("quit") + .alias("exit") + .about("Quit the REPL") + .help_template(APPLET_TEMPLATE), + ) +} + +fn readline() -> Result<String, String> { + write!(std::io::stdout(), "$ ").map_err(|e| e.to_string())?; + std::io::stdout().flush().map_err(|e| e.to_string())?; + let mut buffer = String::new(); + std::io::stdin() + .read_line(&mut buffer) + .map_err(|e| e.to_string())?; + Ok(buffer) +} |