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