use std::net::IpAddr; use std::path::PathBuf; use anyhow::{self, Context}; use mini_async_repl::{ command::{ lift_validation_err, validate, ArgsError, Command, CommandArgInfo, CommandArgType, ExecuteCommand, }, CommandStatus, Repl, }; use std::future::Future; use std::pin::Pin; struct LsCommandHandler {} impl LsCommandHandler { pub fn new() -> Self { Self {} } async fn handle_command(&mut self, dir: PathBuf) -> anyhow::Result { for entry in dir.read_dir()? { println!("{}", entry?.path().to_string_lossy()); } Ok(CommandStatus::Done) } } impl ExecuteCommand for LsCommandHandler { fn execute( &mut self, args: Vec, args_info: Vec, ) -> Pin> + '_>> { let valid = validate(args.clone(), args_info.clone()); if let Err(e) = valid { return Box::pin(lift_validation_err(Err(e))); } let dir_buf: PathBuf = args[0].clone().into(); Box::pin(self.handle_command(dir_buf)) } } struct IpAddrCommandHandler {} impl IpAddrCommandHandler { pub fn new() -> Self { Self {} } async fn handle_command(&mut self, ip: IpAddr) -> anyhow::Result { println!("{}", ip); Ok(CommandStatus::Done) } } impl ExecuteCommand for IpAddrCommandHandler { fn execute( &mut self, args: Vec, args_info: Vec, ) -> Pin> + '_>> { let valid = validate(args.clone(), args_info.clone()); if let Err(e) = valid { return Box::pin(lift_validation_err(Err(e))); } let ip = args[0].parse(); match ip { Ok(ip) => Box::pin(self.handle_command(ip)), Err(e) => Box::pin(lift_validation_err(Err(ArgsError::WrongArgumentValue { argument: args[0].clone(), error: e.to_string(), }))), } } } #[tokio::main] async fn main() -> anyhow::Result<()> { #[rustfmt::skip] let mut repl = Repl::builder() .add("ls", Command::new( "List files in a directory", vec![CommandArgInfo::new_with_name(CommandArgType::Custom, "dir")], Box::new(LsCommandHandler::new()), )) .add("ipaddr", Command::new( "Just parse and print the given IP address".into(), vec![CommandArgInfo::new_with_name(CommandArgType::Custom, "ip")], Box::new(IpAddrCommandHandler::new()), )) .build() .context("Failed to create repl")?; repl.run().await.context("Critical REPL error") }