Skip to main content

agent_air_tui/commands/
registry.rs

1//! Command registry for managing slash commands.
2
3use super::standard::default_commands;
4use super::traits::SlashCommand;
5
6/// Registry of slash commands for an agent.
7///
8/// Provides a builder-style API for configuring which commands are available.
9///
10/// # Example
11///
12/// ```ignore
13/// use agent_air::tui::commands::{
14///     CommandRegistry, CustomCommand, CommandResult,
15///     HelpCommand, ClearCommand, ThemesCommand,
16/// };
17///
18/// // Start with defaults and customize
19/// let commands = CommandRegistry::with_defaults()
20///     .add(CustomCommand::new("deploy", "Deploy the app", |args, ctx| {
21///         CommandResult::Message(format!("Deploying to {}...", args))
22///     }))
23///     .remove("quit")  // Disable quit command
24///     .build();
25///
26/// // Or build from scratch
27/// let commands = CommandRegistry::new()
28///     .add(HelpCommand)
29///     .add(ClearCommand)
30///     .add(ThemesCommand)
31///     .build();
32/// ```
33pub struct CommandRegistry {
34    commands: Vec<Box<dyn SlashCommand>>,
35}
36
37impl CommandRegistry {
38    /// Create an empty registry with no commands.
39    pub fn new() -> Self {
40        Self {
41            commands: Vec::new(),
42        }
43    }
44
45    /// Create a registry with the default commands.
46    ///
47    /// Default commands include: help, clear, compact, themes, sessions,
48    /// status, version, new-session, and quit.
49    pub fn with_defaults() -> Self {
50        Self {
51            commands: default_commands(),
52        }
53    }
54
55    /// Add a command to the registry.
56    ///
57    /// # Example
58    ///
59    /// ```ignore
60    /// registry.add(ClearCommand).add(HelpCommand);
61    /// ```
62    #[allow(clippy::should_implement_trait)]
63    pub fn add<C: SlashCommand + 'static>(mut self, command: C) -> Self {
64        self.commands.push(Box::new(command));
65        self
66    }
67
68    /// Add a boxed command to the registry.
69    ///
70    /// Use this when you already have a `Box<dyn SlashCommand>`.
71    pub fn add_boxed(mut self, command: Box<dyn SlashCommand>) -> Self {
72        self.commands.push(command);
73        self
74    }
75
76    /// Remove a command by name.
77    ///
78    /// # Example
79    ///
80    /// ```ignore
81    /// // Disable the quit command
82    /// registry.remove("quit");
83    /// ```
84    pub fn remove(mut self, name: &str) -> Self {
85        self.commands.retain(|c| c.name() != name);
86        self
87    }
88
89    /// Build into the final command list.
90    ///
91    /// Consumes the registry and returns the commands.
92    pub fn build(self) -> Vec<Box<dyn SlashCommand>> {
93        self.commands
94    }
95
96    /// Get commands as a slice (for inspection without consuming).
97    pub fn commands(&self) -> &[Box<dyn SlashCommand>] {
98        &self.commands
99    }
100}
101
102impl Default for CommandRegistry {
103    fn default() -> Self {
104        Self::with_defaults()
105    }
106}