use std::io::Write; use clap::{Parser, Subcommand}; 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 { let args = shlex::split(line).ok_or("error: Invalid quoting")?; let cli = Cli::try_parse_from(args).map_err(|e| e.to_string())?; match cli.command { Commands::Ping => { write!(std::io::stdout(), "Pong").map_err(|e| e.to_string())?; std::io::stdout().flush().map_err(|e| e.to_string())?; } Commands::Exit => { write!(std::io::stdout(), "Exiting ...").map_err(|e| e.to_string())?; std::io::stdout().flush().map_err(|e| e.to_string())?; return Ok(true); } } Ok(false) } #[derive(Debug, Parser)] #[command(multicall = true)] struct Cli { #[command(subcommand)] command: Commands, } #[derive(Debug, Subcommand)] enum Commands { Ping, Exit, } fn readline() -> Result { 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) }