use std::future::Future;
use std::pin::Pin;
pub type CommandHandler = Box<dyn Fn(Vec<String>) -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + Send>> + Send + Sync>;
pub struct PluginCommand {
pub name: String,
pub description: String,
pub subcommands: Vec<Self>,
pub handler: Option<CommandHandler>,
}
impl std::fmt::Debug for PluginCommand {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PluginCommand")
.field("name", &self.name)
.field("description", &self.description)
.field("subcommands", &self.subcommands)
.field("handler", &self.handler.as_ref().map(|_| "<fn>"))
.finish()
}
}
pub struct PluginCommandBuilder {
name: String,
description: String,
subcommands: Vec<PluginCommand>,
handler: Option<CommandHandler>,
}
impl PluginCommandBuilder {
pub fn new(name: impl Into<String>) -> Self {
Self {
name: name.into(),
description: String::new(),
subcommands: vec![],
handler: None,
}
}
#[must_use]
pub fn description(mut self, desc: impl Into<String>) -> Self {
self.description = desc.into();
self
}
#[must_use]
pub fn subcommand(mut self, cmd: PluginCommand) -> Self {
self.subcommands.push(cmd);
self
}
#[must_use]
pub fn handler<F, Fut>(mut self, f: F) -> Self
where
F: Fn(Vec<String>) -> Fut + Send + Sync + 'static,
Fut: Future<Output = anyhow::Result<()>> + Send + 'static,
{
self.handler = Some(Box::new(move |args| Box::pin(f(args))));
self
}
pub fn build(self) -> PluginCommand {
PluginCommand {
name: self.name,
description: self.description,
subcommands: self.subcommands,
handler: self.handler,
}
}
}