azalea_brigadier/builder/
argument_builder.rs

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