Add async to console commands

This commit is contained in:
fluo10 2025-06-06 07:49:36 +09:00
parent 3e939e8214
commit 0f12dabfc1
2 changed files with 19 additions and 11 deletions

View file

@ -1,7 +1,7 @@
use std::{collections::HashMap, ffi::OsString, hash::Hash, time::Duration}; use std::{collections::HashMap, ffi::OsString, hash::Hash, time::Duration};
use clap::{Args, Parser}; use clap::{Args, Parser};
use futures::StreamExt; use futures::{future::BoxFuture, StreamExt};
use libp2p::{noise, ping, swarm::{NetworkBehaviour, SwarmEvent}, tcp, yamux, Swarm}; use libp2p::{noise, ping, swarm::{NetworkBehaviour, SwarmEvent}, tcp, yamux, Swarm};
use tokio::time::sleep; use tokio::time::sleep;
use tracing_subscriber::EnvFilter; use tracing_subscriber::EnvFilter;
@ -18,22 +18,28 @@ pub trait ConsoleCommand {
fn execute_line(&self, line: String) -> Result<(), Error>; fn execute_line(&self, line: String) -> Result<(), Error>;
} }
pub struct ConsoleCommands { pub struct ConsoleCommands {
content: HashMap<&'static str, Box<dyn Fn(Vec<String>) -> Result<(), Error>>>, content: HashMap<&'static str, Box<dyn Fn(Vec<String>) -> BoxFuture<'static, Result<(), Error>>>>,
} }
impl ConsoleCommands { impl ConsoleCommands {
pub fn new() -> Self { pub fn new() -> Self {
Self{content: HashMap::new()} Self{content: HashMap::new()}
} }
pub fn insert(&mut self,name: &'static str, f: Box<dyn Fn(Vec<String>) -> Result<(), Error>>) { pub fn insert<F, Fut>(&mut self,name: &'static str, f: F)
if let Some(_) = self.content.insert(name, f){ where
F: Fn(Vec<String>) -> Fut + 'static,
Fut: Future<Output = Result<(), Error>> + Send + 'static,
{
if let Some(_) = self.content.insert(name, Box::new(move |v| {
Box::pin(f(v))
})){
unreachable!(); unreachable!();
}; };
} }
pub fn parse_line(&self, line: String) -> Result<(), Error>{ pub async fn parse_and_run(&self, line: String) -> Result<(), Error>{
let args = shell_words::split(&line)?; let args = shell_words::split(&line)?;
if let Some(command_name) = args.first().map(|s| {s.clone()}) { if let Some(command_name) = args.first().map(|s| {s.clone()}) {
if let Some(command) = self.content.get(command_name.as_str()) { if let Some(command) = self.content.get(command_name.as_str()) {
command(args) command(args).await
} else { } else {
println!("Invalid command: {command_name}"); println!("Invalid command: {command_name}");
self.print_commands(); self.print_commands();
@ -53,7 +59,7 @@ impl ConsoleCommands {
impl Default for ConsoleCommands { impl Default for ConsoleCommands {
fn default() -> Self { fn default() -> Self {
let mut commands = Self::new(); let mut commands = Self::new();
commands.insert("node", Box::new(parse_and_run_console_node_command)); commands.insert("node", parse_and_run_console_node_command);
commands commands
} }
} }
@ -74,7 +80,9 @@ impl ConsoleArgs {
let mut rl = rustyline::DefaultEditor::new()?; let mut rl = rustyline::DefaultEditor::new()?;
loop { loop {
match rl.readline(">> ") { match rl.readline(">> ") {
Ok(line) => commands.parse_line(line)?, Ok(line) => {
commands.parse_and_run(line).await?
},
Err(x) => Err(x)?, Err(x) => Err(x)?,
}; };
} }

View file

@ -24,15 +24,15 @@ pub struct ConsoleNodeArgs {
} }
impl ConsoleNodeArgs { impl ConsoleNodeArgs {
pub fn run(self) -> Result<(), Error> { pub async fn run(self) -> Result<(), Error> {
println!("{self:?}"); println!("{self:?}");
Ok(()) Ok(())
} }
} }
pub fn parse_and_run_console_node_command(s:Vec<String>) -> Result<(), Error> { pub async fn parse_and_run_console_node_command(s:Vec<String>) -> Result<(), Error> {
let args = ConsoleNodeArgs::parse_from(s); let args = ConsoleNodeArgs::parse_from(s);
args.run() args.run().await
} }
#[derive(Args, Debug)] #[derive(Args, Debug)]