modcli/
command.rs

1use crate::error::ModCliError;
2/// Defines the trait for commands to implement.
3///
4/// # Example
5/// ```no_run
6/// use modcli::command::Command;
7/// use modcli::ModCli;
8///
9/// struct Hello;
10///
11/// impl Command for Hello {
12///     fn name(&self) -> &str { "hello" }
13///     fn help(&self) -> Option<&str> { Some("Greets the user") }
14///     fn validate(&self, _args: &[String]) -> Result<(), modcli::error::ModCliError> { Ok(()) }
15///     fn execute(&self, _args: &[String]) { println!("Hello!"); }
16/// }
17///
18/// let mut cli = ModCli::new();
19/// cli.registry.register(Box::new(Hello));
20/// let args = vec!["hello".to_string()];
21/// cli.run(args);
22/// ```
23use crate::loader::CommandRegistry;
24
25pub trait Command {
26    fn name(&self) -> &str;
27
28    fn aliases(&self) -> &[&str] {
29        &[]
30    }
31
32    fn help(&self) -> Option<&str> {
33        None
34    }
35
36    fn hidden(&self) -> bool {
37        false
38    }
39
40    /// Capability requirements for visibility/authorization.
41    /// The parent application grants capabilities at runtime on the registry.
42    /// Default: no requirements.
43    fn required_caps(&self) -> &[&str] {
44        &[]
45    }
46
47    fn validate(&self, _args: &[String]) -> Result<(), ModCliError> {
48        Ok(())
49    }
50
51    fn execute(&self, args: &[String]);
52
53    /// Execute with access to the registry context. Default delegates to `execute`.
54    /// Commands that need registry access (e.g., `help`) can override this.
55    fn execute_with(&self, args: &[String], _registry: &CommandRegistry) {
56        self.execute(args)
57    }
58}
59
60// Optional async commands (object-safe via boxed future)
61#[cfg(feature = "async")]
62pub trait AsyncCommand: Send + Sync {
63    fn name(&self) -> &str;
64    fn aliases(&self) -> &[&str] {
65        &[]
66    }
67    fn execute_async<'a>(
68        &'a self,
69        args: &'a [String],
70    ) -> core::pin::Pin<Box<dyn core::future::Future<Output = Result<(), ModCliError>> + Send + 'a>>;
71}