slash_lib/command.rs
1use slash_lang::parser::ast::Arg;
2
3use crate::executor::{CommandOutput, ExecutionError, PipeValue};
4
5/// Describes a single builder-chain method that a command accepts.
6///
7/// Used by the registry to validate `.method()` calls before dispatch.
8#[derive(Debug, Clone, PartialEq)]
9pub struct MethodDef {
10 /// The method name (e.g. `"text"`, `"level"`, `"append"`).
11 pub name: &'static str,
12 /// Whether this method requires a value: `.method(value)` vs `.flag`.
13 pub takes_value: bool,
14}
15
16impl MethodDef {
17 pub const fn flag(name: &'static str) -> Self {
18 Self {
19 name,
20 takes_value: false,
21 }
22 }
23
24 pub const fn with_value(name: &'static str) -> Self {
25 Self {
26 name,
27 takes_value: true,
28 }
29 }
30}
31
32/// Port: a self-contained tool that knows its own methods.
33///
34/// Each implementor is a builtin command (e.g. `/read`, `/exec`, `/find`).
35/// The registry holds these as `Box<dyn SlashCommand>` and dispatches by name.
36pub trait SlashCommand: Send + Sync {
37 /// The command's registered name (e.g. `"read"`, `"exec"`).
38 fn name(&self) -> &str;
39
40 /// The methods this command accepts.
41 ///
42 /// The registry validates all `.method()` args against this list before
43 /// calling [`execute`](Self::execute). Unknown methods are rejected with
44 /// a clear error message.
45 fn methods(&self) -> &[MethodDef];
46
47 /// Execute the command.
48 ///
49 /// - `primary` — the value from `/cmd(value)` syntax, if present.
50 /// - `args` — builder-chain methods, already validated against [`methods`](Self::methods).
51 /// - `input` — piped data from the previous command, if any.
52 fn execute(
53 &self,
54 primary: Option<&str>,
55 args: &[Arg],
56 input: Option<&PipeValue>,
57 ) -> Result<CommandOutput, ExecutionError>;
58}