azalea_brigadier/builder/
argument_builder.rs

1use std::{
2    fmt::{self, Debug},
3    sync::Arc,
4};
5
6use parking_lot::RwLock;
7
8use super::{literal_argument_builder::Literal, required_argument_builder::Argument};
9use crate::{
10    context::CommandContext,
11    errors::CommandSyntaxError,
12    modifier::RedirectModifier,
13    tree::{Command, CommandNode},
14};
15
16#[derive(Debug)]
17pub enum ArgumentBuilderType<S> {
18    Literal(Literal),
19    Argument(Argument<S>),
20}
21impl<S> Clone for ArgumentBuilderType<S> {
22    fn clone(&self) -> Self {
23        match self {
24            ArgumentBuilderType::Literal(literal) => ArgumentBuilderType::Literal(literal.clone()),
25            ArgumentBuilderType::Argument(argument) => {
26                ArgumentBuilderType::Argument(argument.clone())
27            }
28        }
29    }
30}
31
32/// A node that hasn't yet been built.
33#[derive(Clone)]
34pub struct ArgumentBuilder<S> {
35    arguments: CommandNode<S>,
36
37    command: Command<S>,
38    requirement: Arc<dyn Fn(&S) -> bool + Send + Sync>,
39    target: Option<Arc<RwLock<CommandNode<S>>>>,
40
41    forks: bool,
42    modifier: Option<Arc<RedirectModifier<S>>>,
43}
44
45/// A node that isn't yet built.
46impl<S> ArgumentBuilder<S> {
47    pub fn new(value: ArgumentBuilderType<S>) -> Self {
48        Self {
49            arguments: CommandNode {
50                value,
51                ..Default::default()
52            },
53            command: None,
54            requirement: Arc::new(|_| true),
55            forks: false,
56            modifier: None,
57            target: None,
58        }
59    }
60
61    /// Continue building this node with a child node.
62    ///
63    /// ```
64    /// # use azalea_brigadier::prelude::*;
65    /// # let mut subject = CommandDispatcher::<()>::new();
66    /// literal("foo").then(literal("bar").executes(|ctx: &CommandContext<()>| 42))
67    /// # ;
68    /// ```
69    pub fn then(self, argument: ArgumentBuilder<S>) -> Self {
70        self.then_built(argument.build())
71    }
72
73    /// Add an already built child node to this node.
74    ///
75    /// You should usually use [`Self::then`] instead.
76    pub fn then_built(mut self, argument: CommandNode<S>) -> Self {
77        self.arguments.add_child(&Arc::new(RwLock::new(argument)));
78        self
79    }
80
81    /// Set the command to be executed when this node is reached. If this is not
82    /// present on a node, it is not a valid command.
83    ///
84    /// ```
85    /// # use azalea_brigadier::prelude::*;
86    /// # let mut subject = CommandDispatcher::<()>::new();
87    /// # subject.register(
88    /// literal("foo").executes(|ctx: &CommandContext<()>| 42)
89    /// # );
90    /// ```
91    pub fn executes<F>(mut self, f: F) -> Self
92    where
93        F: Fn(&CommandContext<S>) -> i32 + Send + Sync + 'static,
94    {
95        self.command = Some(Arc::new(move |ctx: &CommandContext<S>| Ok(f(ctx))));
96        self
97    }
98
99    /// Same as [`Self::executes`] but returns a `Result<i32,
100    /// CommandSyntaxError>`.
101    pub fn executes_result<F>(mut self, f: F) -> Self
102    where
103        F: Fn(&CommandContext<S>) -> Result<i32, CommandSyntaxError> + Send + Sync + 'static,
104    {
105        self.command = Some(Arc::new(f));
106        self
107    }
108
109    /// Set the requirement for this node to be considered. If this is not
110    /// present on a node, it is considered to always pass.
111    ///
112    /// ```
113    /// # use azalea_brigadier::prelude::*;
114    /// # use std::sync::Arc;
115    /// # pub struct CommandSource {
116    /// #     pub opped: bool,
117    /// # }
118    /// # let mut subject = CommandDispatcher::<CommandSource>::new();
119    /// # subject.register(
120    /// literal("foo")
121    ///     .requires(|s: &CommandSource| s.opped)
122    ///     // ...
123    ///     # .executes(|ctx: &CommandContext<CommandSource>| 42)
124    /// # );
125    pub fn requires<F>(mut self, requirement: F) -> Self
126    where
127        F: Fn(&S) -> bool + Send + Sync + 'static,
128    {
129        self.requirement = Arc::new(requirement);
130        self
131    }
132
133    pub fn redirect(self, target: Arc<RwLock<CommandNode<S>>>) -> Self {
134        self.forward(target, None, false)
135    }
136
137    pub fn fork(
138        self,
139        target: Arc<RwLock<CommandNode<S>>>,
140        modifier: Arc<RedirectModifier<S>>,
141    ) -> Self {
142        self.forward(target, Some(modifier), true)
143    }
144
145    pub fn forward(
146        mut self,
147        target: Arc<RwLock<CommandNode<S>>>,
148        modifier: Option<Arc<RedirectModifier<S>>>,
149        fork: bool,
150    ) -> Self {
151        if !self.arguments.children.is_empty() {
152            panic!("Cannot forward a node with children");
153        }
154        self.target = Some(target);
155        self.modifier = modifier;
156        self.forks = fork;
157        self
158    }
159
160    pub fn arguments(&self) -> &CommandNode<S> {
161        &self.arguments
162    }
163
164    /// Manually build this node into a [`CommandNode`]. You probably don't need
165    /// to do this yourself.
166    pub fn build(self) -> CommandNode<S> {
167        let mut result = CommandNode {
168            value: self.arguments.value,
169            command: self.command,
170            requirement: self.requirement,
171            redirect: self.target,
172            modifier: self.modifier,
173            forks: self.forks,
174            arguments: Default::default(),
175            children: Default::default(),
176            literals: Default::default(),
177        };
178
179        for argument in self.arguments.children.values() {
180            result.add_child(argument);
181        }
182
183        result
184    }
185}
186
187impl<S> Debug for ArgumentBuilder<S> {
188    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
189        f.debug_struct("ArgumentBuilder")
190            .field("arguments", &self.arguments)
191            // .field("command", &self.command)
192            // .field("requirement", &self.requirement)
193            .field("target", &self.target)
194            .field("forks", &self.forks)
195            // .field("modifier", &self.modifier)
196            .finish()
197    }
198}