From 53d51a5ca92aa8ddea9d82b6b44ac7aaa06c2095 Mon Sep 17 00:00:00 2001 From: mat Date: Sun, 7 May 2023 02:50:52 -0500 Subject: more brigadier docs --- azalea-brigadier/README.md | 21 +++++- .../src/arguments/double_argument_type.rs | 2 +- .../src/arguments/float_argument_type.rs | 2 +- .../src/arguments/long_argument_type.rs | 2 +- azalea-brigadier/src/builder/argument_builder.rs | 41 +++++++++++ azalea-brigadier/src/command_dispatcher.rs | 27 ++++++- azalea-brigadier/src/lib.rs | 7 +- azalea-brigadier/tests/command_dispatcher_test.rs | 82 ++++++---------------- 8 files changed, 114 insertions(+), 70 deletions(-) diff --git a/azalea-brigadier/README.md b/azalea-brigadier/README.md index c5aff629..6e573c8b 100755 --- a/azalea-brigadier/README.md +++ b/azalea-brigadier/README.md @@ -4,4 +4,23 @@ A Rust port of Mojang's [Brigadier](https://github.com/Mojang/brigadier) command # Examples -See the [tests](https://github.com/mat-1/azalea/tree/main/azalea-brigadier/tests). +```rust +use azalea_brigadier::prelude::*; +use std::sync::Arc; + +#[derive(Debug, PartialEq)] +struct CommandSource {} + +let mut subject = CommandDispatcher::new(); +subject.register(literal("foo").executes(|_| 42)); + +assert_eq!( + subject + .execute("foo", Arc::new(CommandSource {})) + .unwrap(), + 42 +); +``` + +See the [tests](https://github.com/mat-1/azalea/tree/main/azalea-brigadier/tests) for more. + diff --git a/azalea-brigadier/src/arguments/double_argument_type.rs b/azalea-brigadier/src/arguments/double_argument_type.rs index 117a11cc..d83bfb2a 100644 --- a/azalea-brigadier/src/arguments/double_argument_type.rs +++ b/azalea-brigadier/src/arguments/double_argument_type.rs @@ -45,7 +45,7 @@ impl ArgumentType for Double { pub fn double() -> impl ArgumentType { Double::default() } -pub fn get_integer(context: &CommandContext, name: &str) -> Option { +pub fn get_double(context: &CommandContext, name: &str) -> Option { context .argument(name) .unwrap() diff --git a/azalea-brigadier/src/arguments/float_argument_type.rs b/azalea-brigadier/src/arguments/float_argument_type.rs index f335f11a..0d194efe 100644 --- a/azalea-brigadier/src/arguments/float_argument_type.rs +++ b/azalea-brigadier/src/arguments/float_argument_type.rs @@ -45,7 +45,7 @@ impl ArgumentType for Float { pub fn float() -> impl ArgumentType { Float::default() } -pub fn get_integer(context: &CommandContext, name: &str) -> Option { +pub fn get_float(context: &CommandContext, name: &str) -> Option { context .argument(name) .unwrap() diff --git a/azalea-brigadier/src/arguments/long_argument_type.rs b/azalea-brigadier/src/arguments/long_argument_type.rs index 435dd92a..9b3469b6 100644 --- a/azalea-brigadier/src/arguments/long_argument_type.rs +++ b/azalea-brigadier/src/arguments/long_argument_type.rs @@ -45,7 +45,7 @@ impl ArgumentType for Long { pub fn long() -> impl ArgumentType { Long::default() } -pub fn get_integer(context: &CommandContext, name: &str) -> Option { +pub fn get_long(context: &CommandContext, name: &str) -> Option { context .argument(name) .unwrap() diff --git a/azalea-brigadier/src/builder/argument_builder.rs b/azalea-brigadier/src/builder/argument_builder.rs index c6f2146a..643a3bd0 100755 --- a/azalea-brigadier/src/builder/argument_builder.rs +++ b/azalea-brigadier/src/builder/argument_builder.rs @@ -43,15 +43,38 @@ impl ArgumentBuilder { } } + /// 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) -> i32 + Send + Sync + 'static, @@ -60,6 +83,22 @@ impl ArgumentBuilder { 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: Arc| s.opped) + /// // ... + /// # .executes(|ctx: &CommandContext| 42) + /// # ); pub fn requires(mut self, requirement: F) -> Self where F: Fn(Arc) -> bool + Send + Sync + 'static, @@ -95,6 +134,8 @@ impl ArgumentBuilder { self } + /// 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, diff --git a/azalea-brigadier/src/command_dispatcher.rs b/azalea-brigadier/src/command_dispatcher.rs index a14b5009..595bc57d 100755 --- a/azalea-brigadier/src/command_dispatcher.rs +++ b/azalea-brigadier/src/command_dispatcher.rs @@ -11,6 +11,12 @@ use crate::{ use std::{cmp::Ordering, collections::HashMap, mem, rc::Rc, sync::Arc}; /// The root of the command tree. You need to make this to register commands. +/// +/// ``` +/// # use azalea_brigadier::prelude::*; +/// # struct CommandSource; +/// let mut subject = CommandDispatcher::::new(); +/// ``` pub struct CommandDispatcher where Self: Sync + Send, @@ -25,13 +31,22 @@ impl CommandDispatcher { } } + /// Add a new node to the root. + /// + /// ``` + /// # use azalea_brigadier::prelude::*; + /// # let mut subject = CommandDispatcher::<()>::new(); + /// subject.register(literal("foo").executes(|_| 42)); + /// ``` pub fn register(&mut self, node: ArgumentBuilder) -> Arc>> { let build = Arc::new(RwLock::new(node.build())); self.root.write().add_child(&build); build } - pub fn parse(&self, command: StringReader, source: Arc) -> ParseResults { + pub fn parse(&self, command: StringReader, source: S) -> ParseResults { + let source = Arc::new(source); + let context = CommandContextBuilder::new(self, source, self.root.clone(), command.cursor()); self.parse_nodes(&self.root, &command, context).unwrap() } @@ -140,11 +155,17 @@ impl CommandDispatcher { }) } + /// Parse and execute the command using the given input and context. The + /// number returned depends on the command, and may not be of significance. + /// + /// This is a shortcut for `Self::parse` and `Self::execute_parsed`. pub fn execute( &self, - input: StringReader, - source: Arc, + input: impl Into, + source: S, ) -> Result { + let input = input.into(); + let parse = self.parse(input, source); Self::execute_parsed(parse) } diff --git a/azalea-brigadier/src/lib.rs b/azalea-brigadier/src/lib.rs index 8b8e116e..161ef83a 100755 --- a/azalea-brigadier/src/lib.rs +++ b/azalea-brigadier/src/lib.rs @@ -14,8 +14,11 @@ pub mod tree; pub mod prelude { pub use crate::{ arguments::{ - double_argument_type::double, float_argument_type::float, - integer_argument_type::integer, long_argument_type::long, string_argument_type::string, + double_argument_type::{double, get_double}, + float_argument_type::{float, get_float}, + integer_argument_type::{get_integer, integer}, + long_argument_type::{get_long, long}, + string_argument_type::{get_string, greedy_string, string, word}, }, builder::{literal_argument_builder::literal, required_argument_builder::argument}, command_dispatcher::CommandDispatcher, diff --git a/azalea-brigadier/tests/command_dispatcher_test.rs b/azalea-brigadier/tests/command_dispatcher_test.rs index 4479cfa2..eecbf668 100755 --- a/azalea-brigadier/tests/command_dispatcher_test.rs +++ b/azalea-brigadier/tests/command_dispatcher_test.rs @@ -18,19 +18,6 @@ fn input_with_offset(input: &str, offset: usize) -> StringReader { result } -#[test] -fn create_and_execute_command() { - let mut subject = CommandDispatcher::new(); - subject.register(literal("foo").executes(|_| 42)); - - assert_eq!( - subject - .execute("foo".into(), Arc::new(CommandSource {})) - .unwrap(), - 42 - ); -} - #[test] fn create_and_execute_offset_command() { let mut subject = CommandDispatcher::new(); @@ -38,7 +25,7 @@ fn create_and_execute_offset_command() { assert_eq!( subject - .execute(input_with_offset("/foo", 1), Arc::new(CommandSource {})) + .execute(input_with_offset("/foo", 1), &CommandSource {}) .unwrap(), 42 ); @@ -50,18 +37,8 @@ fn create_and_merge_commands() { subject.register(literal("base").then(literal("foo").executes(|_| 42))); subject.register(literal("base").then(literal("bar").executes(|_| 42))); - assert_eq!( - subject - .execute("base foo".into(), Arc::new(CommandSource {})) - .unwrap(), - 42 - ); - assert_eq!( - subject - .execute("base bar".into(), Arc::new(CommandSource {})) - .unwrap(), - 42 - ); + assert_eq!(subject.execute("base foo", &CommandSource {}).unwrap(), 42); + assert_eq!(subject.execute("base bar", &CommandSource {}).unwrap(), 42); } #[test] @@ -70,7 +47,7 @@ fn execute_unknown_command() { subject.register(literal("bar")); subject.register(literal("baz")); - let execute_result = subject.execute("foo".into(), Arc::new(CommandSource {})); + let execute_result = subject.execute("foo", &CommandSource {}); let err = execute_result.err().unwrap(); match err.type_ { @@ -85,7 +62,7 @@ fn execute_impermissible_command() { let mut subject = CommandDispatcher::new(); subject.register(literal("foo").requires(|_| false)); - let execute_result = subject.execute("foo".into(), Arc::new(CommandSource {})); + let execute_result = subject.execute("foo", &CommandSource {}); let err = execute_result.err().unwrap(); match err.type_ { @@ -100,7 +77,7 @@ fn execute_empty_command() { let mut subject = CommandDispatcher::new(); subject.register(literal("")); - let execute_result = subject.execute("".into(), Arc::new(CommandSource {})); + let execute_result = subject.execute("", &CommandSource {}); let err = execute_result.err().unwrap(); match err.type_ { @@ -115,7 +92,7 @@ fn execute_unknown_subcommand() { let mut subject = CommandDispatcher::new(); subject.register(literal("foo").executes(|_| 42)); - let execute_result = subject.execute("foo bar".into(), Arc::new(CommandSource {})); + let execute_result = subject.execute("foo bar", &CommandSource {}); let err = execute_result.err().unwrap(); match err.type_ { @@ -130,7 +107,7 @@ fn execute_incorrect_literal() { let mut subject = CommandDispatcher::new(); subject.register(literal("foo").executes(|_| 42).then(literal("bar"))); - let execute_result = subject.execute("foo baz".into(), Arc::new(CommandSource {})); + let execute_result = subject.execute("foo baz", &CommandSource {}); let err = execute_result.err().unwrap(); match err.type_ { @@ -150,7 +127,7 @@ fn execute_ambiguous_incorrect_argument() { .then(literal("baz")), ); - let execute_result = subject.execute("foo unknown".into(), Arc::new(CommandSource {})); + let execute_result = subject.execute("foo unknown", &CommandSource {}); let err = execute_result.err().unwrap(); match err.type_ { @@ -172,12 +149,7 @@ fn execute_subcommand() { .executes(|_| 42), ); - assert_eq!( - subject - .execute("foo =".into(), Arc::new(CommandSource {})) - .unwrap(), - 100 - ); + assert_eq!(subject.execute("foo =", &CommandSource {}).unwrap(), 100); } #[test] @@ -185,7 +157,7 @@ fn parse_incomplete_literal() { let mut subject = CommandDispatcher::new(); subject.register(literal("foo").then(literal("bar").executes(|_| 42))); - let parse = subject.parse("foo ".into(), Arc::new(CommandSource {})); + let parse = subject.parse("foo ".into(), &CommandSource {}); assert_eq!(parse.reader.remaining(), " "); assert_eq!(parse.context.nodes.len(), 1); } @@ -195,7 +167,7 @@ fn parse_incomplete_argument() { let mut subject = CommandDispatcher::new(); subject.register(literal("foo").then(argument("bar", integer()).executes(|_| 42))); - let parse = subject.parse("foo ".into(), Arc::new(CommandSource {})); + let parse = subject.parse("foo ".into(), &CommandSource {}); assert_eq!(parse.reader.remaining(), " "); assert_eq!(parse.context.nodes.len(), 1); } @@ -210,12 +182,7 @@ fn execute_ambiguious_parent_subcommand() { .then(argument("right", integer()).then(argument("sub", integer()).executes(|_| 100))), ); - assert_eq!( - subject - .execute("test 1 2".into(), Arc::new(CommandSource {})) - .unwrap(), - 100 - ); + assert_eq!(subject.execute("test 1 2", &CommandSource {}).unwrap(), 100); } #[test] @@ -231,9 +198,7 @@ fn execute_ambiguious_parent_subcommand_via_redirect() { subject.register(literal("redirect").redirect(real)); assert_eq!( - subject - .execute("redirect 1 2".into(), Arc::new(CommandSource {})) - .unwrap(), + subject.execute("redirect 1 2", &CommandSource {}).unwrap(), 100 ); } @@ -248,7 +213,7 @@ fn execute_redirected_multiple_times() { let input = "redirected redirected actual"; - let parse = subject.parse(input.into(), Arc::new(CommandSource {})); + let parse = subject.parse(input.into(), &CommandSource {}); assert_eq!(parse.context.range.get(input), "redirected"); assert_eq!(parse.context.nodes.len(), 1); assert_eq!(*parse.context.root.read(), *root.read()); @@ -299,7 +264,7 @@ fn execute_redirected() { subject.register(literal("redirected").fork(subject.root.clone(), Arc::new(modifier))); let input = "redirected actual"; - let parse = subject.parse(input.into(), Arc::new(CommandSource {})); + let parse = subject.parse(input.into(), CommandSource {}); assert_eq!(parse.context.range.get(input), "redirected"); assert_eq!(parse.context.nodes.len(), 1); assert_eq!(*parse.context.root.read(), *subject.root.read()); @@ -314,7 +279,7 @@ fn execute_redirected() { assert_eq!(*parse.context.root.read(), *subject.root.read()); assert_eq!(parent.nodes[0].range, parent.range); assert_eq!(*parent.nodes[0].node.read(), *concrete_node.read()); - assert_eq!(parent.source, Arc::new(CommandSource {})); + assert_eq!(*parent.source, CommandSource {}); assert_eq!(CommandDispatcher::execute_parsed(parse).unwrap(), 2); } @@ -329,7 +294,7 @@ fn execute_orphaned_subcommand() { .executes(|_| 42), ); - let result = subject.execute("foo 5".into(), Arc::new(CommandSource {})); + let result = subject.execute("foo 5", &CommandSource {}); assert!(result.is_err()); let result = result.unwrap_err(); assert_eq!( @@ -346,12 +311,7 @@ fn execute_invalid_other() { subject.register(literal("w").executes(|_| panic!("This should not run"))); subject.register(literal("world").executes(|_| 42)); - assert_eq!( - subject - .execute("world".into(), Arc::new(CommandSource {})) - .unwrap(), - 42 - ); + assert_eq!(subject.execute("world", &CommandSource {}).unwrap(), 42); } #[test] @@ -364,7 +324,7 @@ fn parse_no_space_separator() { .executes(|_| 42), ); - let result = subject.execute("foo$".into(), Arc::new(CommandSource {})); + let result = subject.execute("foo$", &CommandSource {}); assert!(result.is_err()); let result = result.unwrap_err(); assert_eq!( @@ -384,7 +344,7 @@ fn execute_invalid_subcommand() { .executes(|_| 42), ); - let result = subject.execute("foo bar".into(), Arc::new(CommandSource {})); + let result = subject.execute("foo bar", &CommandSource {}); assert!(result.is_err()); let result = result.unwrap_err(); // this fails for some reason, i blame mojang -- cgit v1.2.3