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}