1use std::future::Future;
2use std::pin::Pin;
3
4pub type CommandHandler = Box<dyn Fn(Vec<String>) -> Pin<Box<dyn Future<Output = anyhow::Result<()>> + Send>> + Send + Sync>;
6
7pub struct PluginCommand {
12 pub name: String,
13 pub description: String,
14 pub subcommands: Vec<Self>,
15 pub handler: Option<CommandHandler>,
16}
17
18impl std::fmt::Debug for PluginCommand {
19 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20 f.debug_struct("PluginCommand")
21 .field("name", &self.name)
22 .field("description", &self.description)
23 .field("subcommands", &self.subcommands)
24 .field("handler", &self.handler.as_ref().map(|_| "<fn>"))
25 .finish()
26 }
27}
28
29pub struct PluginCommandBuilder {
31 name: String,
32 description: String,
33 subcommands: Vec<PluginCommand>,
34 handler: Option<CommandHandler>,
35}
36
37impl PluginCommandBuilder {
38 pub fn new(name: impl Into<String>) -> Self {
40 Self {
41 name: name.into(),
42 description: String::new(),
43 subcommands: vec![],
44 handler: None,
45 }
46 }
47
48 #[must_use]
50 pub fn description(mut self, desc: impl Into<String>) -> Self {
51 self.description = desc.into();
52 self
53 }
54
55 #[must_use]
57 pub fn subcommand(mut self, cmd: PluginCommand) -> Self {
58 self.subcommands.push(cmd);
59 self
60 }
61
62 #[must_use]
64 pub fn handler<F, Fut>(mut self, f: F) -> Self
65 where
66 F: Fn(Vec<String>) -> Fut + Send + Sync + 'static,
67 Fut: Future<Output = anyhow::Result<()>> + Send + 'static,
68 {
69 self.handler = Some(Box::new(move |args| Box::pin(f(args))));
70 self
71 }
72
73 pub fn build(self) -> PluginCommand {
75 PluginCommand {
76 name: self.name,
77 description: self.description,
78 subcommands: self.subcommands,
79 handler: self.handler,
80 }
81 }
82}