Add ConsoleCommands

This commit is contained in:
fluo10 2025-06-06 06:50:28 +09:00
parent 10fc2d9946
commit 3e939e8214
6 changed files with 92 additions and 13 deletions

View file

@ -18,9 +18,11 @@ clap = { version = "4.5.38", features = ["derive"] }
dirs = "6.0.0" dirs = "6.0.0"
futures = "0.3.31" futures = "0.3.31"
libp2p.workspace = true libp2p.workspace = true
rustyline = "16.0.0"
sea-orm = { version = "1.1.11", features = ["sqlx-sqlite", "runtime-tokio-native-tls", "macros", "with-chrono", "with-uuid"] } sea-orm = { version = "1.1.11", features = ["sqlx-sqlite", "runtime-tokio-native-tls", "macros", "with-chrono", "with-uuid"] }
sea-orm-migration.workspace = true sea-orm-migration.workspace = true
serde = { version = "1.0.219", features = ["derive"] } serde = { version = "1.0.219", features = ["derive"] }
shell-words = "1.1.0"
tempfile = { version = "3.20.0", optional = true } tempfile = { version = "3.20.0", optional = true }
thiserror = "2.0.12" thiserror = "2.0.12"
tokio = { version = "1.45.0", features = ["macros", "rt"] } tokio = { version = "1.45.0", features = ["macros", "rt"] }

View file

@ -1,6 +1,6 @@
use std::time::Duration; use std::{collections::HashMap, ffi::OsString, hash::Hash, time::Duration};
use clap::Args; use clap::{Args, Parser};
use futures::StreamExt; use futures::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;
@ -8,7 +8,55 @@ use tracing_subscriber::EnvFilter;
use crate::{error::Error, global::GLOBAL}; use crate::{error::Error, global::GLOBAL};
use super::ConfigArgs; use super::{node::parse_and_run_console_node_command, ConfigArgs};
pub trait Executable {
fn execute(self) -> Result<(), Error>;
}
pub trait ConsoleCommand {
fn execute_line(&self, line: String) -> Result<(), Error>;
}
pub struct ConsoleCommands {
content: HashMap<&'static str, Box<dyn Fn(Vec<String>) -> Result<(), Error>>>,
}
impl ConsoleCommands {
pub fn new() -> Self {
Self{content: HashMap::new()}
}
pub fn insert(&mut self,name: &'static str, f: Box<dyn Fn(Vec<String>) -> Result<(), Error>>) {
if let Some(_) = self.content.insert(name, f){
unreachable!();
};
}
pub fn parse_line(&self, line: String) -> Result<(), Error>{
let args = shell_words::split(&line)?;
if let Some(command_name) = args.first().map(|s| {s.clone()}) {
if let Some(command) = self.content.get(command_name.as_str()) {
command(args)
} else {
println!("Invalid command: {command_name}");
self.print_commands();
Ok(())
}
} else {
Ok(())
}
}
pub fn print_commands(&self) {
for key in self.content.keys(){
println!("{key}");
}
}
}
impl Default for ConsoleCommands {
fn default() -> Self {
let mut commands = Self::new();
commands.insert("node", Box::new(parse_and_run_console_node_command));
commands
}
}
#[derive(Args, Debug)] #[derive(Args, Debug)]
pub struct ConsoleArgs { pub struct ConsoleArgs {
@ -17,12 +65,19 @@ pub struct ConsoleArgs {
} }
impl ConsoleArgs { impl ConsoleArgs {
pub async fn start_console(self) -> Result<(), Error>{ pub async fn start_console(self, commands: ConsoleCommands) -> Result<(), Error>
{
let _ = crate::global::GLOBAL.get_or_init_node_config(self.config.try_into_node_config().await?).await; let _ = crate::global::GLOBAL.get_or_init_node_config(self.config.try_into_node_config().await?).await;
tokio::spawn( async { tokio::spawn( async {
GLOBAL.launch_swarm().await GLOBAL.launch_swarm().await
}); });
sleep(Duration::from_secs(1)).await; let mut rl = rustyline::DefaultEditor::new()?;
Ok(()) loop {
match rl.readline(">> ") {
Ok(line) => commands.parse_line(line)?,
Err(x) => Err(x)?,
};
}
} }
} }

View file

@ -7,7 +7,7 @@ mod node;
mod server; mod server;
pub use config::ConfigArgs; pub use config::ConfigArgs;
pub use console::ConsoleArgs; pub use console::{ConsoleArgs, ConsoleCommands};
pub use init::InitArgs; pub use init::InitArgs;
pub use node::{ NodeArgs, NodeCommand, JoinNodeArgs }; pub use node::{ NodeArgs, NodeCommand, JoinNodeArgs , ConsoleNodeArgs};
pub use server::ServerArgs; pub use server::ServerArgs;

View file

@ -1,6 +1,6 @@
use std::{net::IpAddr, path::PathBuf}; use std::{net::IpAddr, path::PathBuf};
use clap::{Args, Subcommand}; use clap::{Args, Parser, Subcommand};
use futures::StreamExt; use futures::StreamExt;
use libp2p::{ use libp2p::{
multiaddr::Protocol, noise, ping, swarm::SwarmEvent, tcp, yamux, Multiaddr multiaddr::Protocol, noise, ping, swarm::SwarmEvent, tcp, yamux, Multiaddr
@ -11,12 +11,30 @@ use crate::{cli::ServerArgs, error::Error};
use super::ConfigArgs; use super::ConfigArgs;
#[derive(Args, Debug)] #[derive(Debug, Args)]
pub struct NodeArgs { pub struct NodeArgs {
#[command(subcommand)] #[command(subcommand)]
pub command: NodeCommand pub command: NodeCommand
} }
#[derive(Debug, Parser)]
pub struct ConsoleNodeArgs {
#[command(flatten)]
pub args: NodeArgs,
}
impl ConsoleNodeArgs {
pub fn run(self) -> Result<(), Error> {
println!("{self:?}");
Ok(())
}
}
pub fn parse_and_run_console_node_command(s:Vec<String>) -> Result<(), Error> {
let args = ConsoleNodeArgs::parse_from(s);
args.run()
}
#[derive(Args, Debug)] #[derive(Args, Debug)]
pub struct JoinNodeArgs { pub struct JoinNodeArgs {
#[arg(long)] #[arg(long)]

View file

@ -18,6 +18,10 @@ pub enum Error {
Multiaddr(#[from] libp2p::multiaddr::Error), Multiaddr(#[from] libp2p::multiaddr::Error),
#[error("Noise error: {0}")] #[error("Noise error: {0}")]
Noise(#[from] libp2p::noise::Error), Noise(#[from] libp2p::noise::Error),
#[error("Readline error: {0}")]
Readline(#[from] rustyline::error::ReadlineError),
#[error("Shell word split error: {0}")]
ShellWord(#[from] shell_words::ParseError),
#[error("toml deserialization error: {0}")] #[error("toml deserialization error: {0}")]
TomlDe(#[from] toml::de::Error), TomlDe(#[from] toml::de::Error),
#[error("toml serialization error: {0}")] #[error("toml serialization error: {0}")]

View file

@ -1,5 +1,5 @@
use clap::{Parser, Subcommand}; use clap::{Parser, Subcommand};
use lazy_supplements::{cli::{ConsoleArgs, InitArgs, NodeArgs, NodeCommand, ServerArgs}, *}; use lazy_supplements::{cli::{ConsoleArgs, ConsoleCommands, InitArgs, NodeArgs, NodeCommand, ServerArgs}, *};
#[derive(Debug, Parser)] #[derive(Debug, Parser)]
struct Cli { struct Cli {
@ -25,6 +25,6 @@ async fn main() {
}, },
Command::Init(x) => x.init_config().await, Command::Init(x) => x.init_config().await,
Command::Server(x) => x.start_server().await.unwrap(), Command::Server(x) => x.start_server().await.unwrap(),
Command::Console(x) => x.start_console().await.unwrap(), Command::Console(x) => x.start_console(ConsoleCommands::default()).await.unwrap(),
} }
} }