agent_core/tui/commands/custom.rs
1//! Custom command helper for closure-based commands.
2
3use super::context::CommandContext;
4use super::result::CommandResult;
5use super::traits::SlashCommand;
6
7/// A simple custom command using a closure.
8///
9/// Use this for commands that don't need internal state.
10/// For stateful commands, implement [`SlashCommand`] directly.
11///
12/// # Example
13///
14/// ```ignore
15/// use agent_core::tui::commands::{CustomCommand, CommandResult};
16///
17/// let cmd = CustomCommand::new(
18/// "greet",
19/// "Say hello to someone",
20/// |args, ctx| {
21/// let name = if args.is_empty() { "World" } else { args };
22/// CommandResult::Message(format!("Hello, {}!", name))
23/// },
24/// );
25/// ```
26pub struct CustomCommand {
27 name: String,
28 description: String,
29 handler: Box<dyn Fn(&str, &mut CommandContext) -> CommandResult + Send + Sync>,
30}
31
32impl CustomCommand {
33 /// Create a new custom command.
34 ///
35 /// # Arguments
36 /// * `name` - Command name without the leading slash
37 /// * `description` - Short description shown in the popup
38 /// * `handler` - Closure that executes the command
39 pub fn new<F>(name: impl Into<String>, description: impl Into<String>, handler: F) -> Self
40 where
41 F: Fn(&str, &mut CommandContext) -> CommandResult + Send + Sync + 'static,
42 {
43 Self {
44 name: name.into(),
45 description: description.into(),
46 handler: Box::new(handler),
47 }
48 }
49}
50
51impl SlashCommand for CustomCommand {
52 fn name(&self) -> &str {
53 &self.name
54 }
55
56 fn description(&self) -> &str {
57 &self.description
58 }
59
60 fn execute(&self, args: &str, ctx: &mut CommandContext) -> CommandResult {
61 (self.handler)(args, ctx)
62 }
63}