use std::{ fmt::{self, Debug}, sync::Arc, }; use parking_lot::RwLock; use super::{literal_argument_builder::Literal, required_argument_builder::Argument}; use crate::{ context::CommandContext, errors::CommandSyntaxError, modifier::RedirectModifier, tree::{Command, CommandNode}, }; #[derive(Debug)] pub enum ArgumentBuilderType { Literal(Literal), Argument(Argument), } impl Clone for ArgumentBuilderType { fn clone(&self) -> Self { match self { ArgumentBuilderType::Literal(literal) => ArgumentBuilderType::Literal(literal.clone()), ArgumentBuilderType::Argument(argument) => { ArgumentBuilderType::Argument(argument.clone()) } } } } /// A node that hasn't yet been built. pub struct ArgumentBuilder { arguments: CommandNode, command: Command, requirement: Arc bool + Send + Sync>, target: Option>>>, forks: bool, modifier: Option>>, } /// A node that isn't yet built. impl ArgumentBuilder { pub fn new(value: ArgumentBuilderType) -> Self { Self { arguments: CommandNode { value, ..Default::default() }, command: None, requirement: Arc::new(|_| true), forks: false, modifier: None, target: None, } } /// Continue building this node with a child node. /// /// ``` /// # use azalea_brigadier::prelude::*; /// # let mut subject = CommandDispatcher::<()>::new(); /// literal("foo").then(literal("bar").executes(|ctx: &CommandContext<()>| 42)) /// # ; /// ``` pub fn then(self, argument: ArgumentBuilder) -> Self { self.then_built(argument.build()) } /// Add an already built child node to this node. /// /// You should usually use [`Self::then`] instead. pub fn then_built(mut self, argument: CommandNode) -> Self { self.arguments.add_child(&Arc::new(RwLock::new(argument))); self } /// Set the command to be executed when this node is reached. /// /// If this is not present on a node, it is not a valid command. /// /// ``` /// # use azalea_brigadier::prelude::*; /// # let mut subject = CommandDispatcher::<()>::new(); /// # subject.register( /// literal("foo").executes(|ctx: &CommandContext<()>| 42) /// # ); /// ``` pub fn executes(mut self, f: F) -> Self where F: Fn(&CommandContext) -> R + Send + Sync + 'static, { self.command = Some(Arc::new(move |ctx: &CommandContext| Ok(f(ctx)))); self } /// Same as [`Self::executes`] but returns a `Result`. pub fn executes_result(mut self, f: F) -> Self where F: Fn(&CommandContext) -> Result + Send + Sync + 'static, { self.command = Some(Arc::new(f)); self } /// Set the requirement for this node to be considered. /// /// If this is not present on a node, it is considered to always pass. /// /// ``` /// # use azalea_brigadier::prelude::*; /// # use std::sync::Arc; /// # pub struct CommandSource { /// # pub opped: bool, /// # } /// # let mut subject = CommandDispatcher::::new(); /// # subject.register( /// literal("foo") /// .requires(|s: &CommandSource| s.opped) /// // ... /// # .executes(|ctx: &CommandContext| 42) /// # ); pub fn requires(mut self, requirement: F) -> Self where F: Fn(&S) -> bool + Send + Sync + 'static, { self.requirement = Arc::new(requirement); self } pub fn redirect(self, target: Arc>>) -> Self { self.forward(target, None, false) } pub fn fork( self, target: Arc>>, modifier: Arc>, ) -> Self { self.forward(target, Some(modifier), true) } pub fn forward( mut self, target: Arc>>, modifier: Option>>, fork: bool, ) -> Self { if !self.arguments.children.is_empty() { panic!("Cannot forward a node with children"); } self.target = Some(target); self.modifier = modifier; self.forks = fork; self } pub fn arguments(&self) -> &CommandNode { &self.arguments } /// Manually build this node into a [`CommandNode`]. You probably don't need /// to do this yourself. pub fn build(self) -> CommandNode { let mut result = CommandNode { value: self.arguments.value, command: self.command, requirement: self.requirement, redirect: self.target, modifier: self.modifier, forks: self.forks, arguments: Default::default(), children: Default::default(), literals: Default::default(), }; for argument in self.arguments.children.values() { result.add_child(argument); } result } } impl Debug for ArgumentBuilder { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("ArgumentBuilder") .field("arguments", &self.arguments) // .field("command", &self.command) // .field("requirement", &self.requirement) .field("target", &self.target) .field("forks", &self.forks) // .field("modifier", &self.modifier) .finish() } } impl Clone for ArgumentBuilder { fn clone(&self) -> Self { Self { arguments: self.arguments.clone(), command: self.command.clone(), requirement: self.requirement.clone(), target: self.target.clone(), forks: self.forks, modifier: self.modifier.clone(), } } }