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}