From fec7a2bfedc562306523b9d3c51b97e376dc32d9 Mon Sep 17 00:00:00 2001 From: mat Date: Sun, 9 Jan 2022 23:46:23 -0600 Subject: [PATCH] AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA --- .../src/arguments/argument_type.rs | 12 +- .../src/arguments/bool_argument_type.rs | 2 +- .../src/builder/argument_builder.rs | 7 +- .../src/builder/required_argument_builder.rs | 120 ++++++++++++++++++ azalea-brigadier/src/command_dispatcher.rs | 2 + .../src/context/command_context.rs | 6 +- .../src/context/command_context_builder.rs | 14 +- .../src/context/parsed_argument.rs | 6 +- .../src/tree/argument_command_node.rs | 11 +- azalea-brigadier/src/tree/command_node.rs | 11 +- 10 files changed, 160 insertions(+), 31 deletions(-) diff --git a/azalea-brigadier/src/arguments/argument_type.rs b/azalea-brigadier/src/arguments/argument_type.rs index 34d57285..ea453a1a 100644 --- a/azalea-brigadier/src/arguments/argument_type.rs +++ b/azalea-brigadier/src/arguments/argument_type.rs @@ -5,7 +5,12 @@ use crate::{ suggestion::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder}, }; -pub trait ArgumentType { +pub trait ArgumentResult {} + +pub trait ArgumentType +where + T: ArgumentResult, +{ // T parse(StringReader reader) throws CommandSyntaxException; // default CompletableFuture listSuggestions(final CommandContext context, final SuggestionsBuilder builder) { @@ -16,12 +21,13 @@ pub trait ArgumentType { // return Collections.emptyList(); // } - fn parse(reader: &mut StringReader) -> Result; + fn parse(&self, reader: &mut StringReader) -> Result; fn list_suggestions( + &self, context: &CommandContext, builder: &mut SuggestionsBuilder, ) -> Result; - fn get_examples() -> Vec; + fn get_examples(&self) -> Vec; } diff --git a/azalea-brigadier/src/arguments/bool_argument_type.rs b/azalea-brigadier/src/arguments/bool_argument_type.rs index f4c03373..74df3331 100644 --- a/azalea-brigadier/src/arguments/bool_argument_type.rs +++ b/azalea-brigadier/src/arguments/bool_argument_type.rs @@ -4,7 +4,7 @@ use super::argument_type::ArgumentType; struct BoolArgumentType {} -impl ArgumentType for BoolArgumentType {} +impl ArgumentType for BoolArgumentType {} impl BoolArgumentType { const EXAMPLES: &'static [&'static str] = &["true", "false"]; diff --git a/azalea-brigadier/src/builder/argument_builder.rs b/azalea-brigadier/src/builder/argument_builder.rs index 8a64a9e4..19706a22 100644 --- a/azalea-brigadier/src/builder/argument_builder.rs +++ b/azalea-brigadier/src/builder/argument_builder.rs @@ -10,7 +10,7 @@ where T: ArgumentBuilder, { arguments: RootCommandNode, - command: dyn Command, + command: Option>, requirement: dyn Fn(&S) -> bool, target: Option>, modifier: Option>, @@ -18,7 +18,6 @@ where } pub trait ArgumentBuilder { - fn this() -> T; fn build(self) -> dyn CommandNode; } @@ -92,11 +91,11 @@ where Ok(self) } - pub fn redirect(&self) -> Option<&dyn CommandNode> { + pub fn get_redirect(&self) -> Option<&dyn CommandNode> { self.target.as_ref() } - pub fn redirect_modifier(&self) -> Option<&dyn RedirectModifier> { + pub fn get_redirect_modifier(&self) -> Option<&dyn RedirectModifier> { self.modifier.as_ref() } diff --git a/azalea-brigadier/src/builder/required_argument_builder.rs b/azalea-brigadier/src/builder/required_argument_builder.rs index e69de29b..3ec613c4 100644 --- a/azalea-brigadier/src/builder/required_argument_builder.rs +++ b/azalea-brigadier/src/builder/required_argument_builder.rs @@ -0,0 +1,120 @@ +use crate::{ + arguments::argument_type::ArgumentType, + suggestion::suggestion_provider::SuggestionProvider, + tree::{argument_command_node::ArgumentCommandNode, command_node::BaseCommandNode}, +}; + +use super::argument_builder::BaseArgumentBuilder; + +// private RequiredArgumentBuilder(final String name, final ArgumentType type) { +// this.name = name; +// this.type = type; +// } + +// public static RequiredArgumentBuilder argument(final String name, final ArgumentType type) { +// return new RequiredArgumentBuilder<>(name, type); +// } + +// public RequiredArgumentBuilder suggests(final SuggestionProvider provider) { +// this.suggestionsProvider = provider; +// return getThis(); +// } + +// public SuggestionProvider getSuggestionsProvider() { +// return suggestionsProvider; +// } + +// @Override +// protected RequiredArgumentBuilder getThis() { +// return this; +// } + +// public ArgumentType getType() { +// return type; +// } + +// public String getName() { +// return name; +// } + +// public ArgumentCommandNode build() { +// final ArgumentCommandNode result = new ArgumentCommandNode<>(getName(), getType(), getCommand(), getRequirement(), getRedirect(), getRedirectModifier(), isFork(), getSuggestionsProvider()); + +// for (final CommandNode argument : getArguments()) { +// result.addChild(argument); +// } + +// return result; +// } + +pub struct RequiredArgumentBuilder { + // private final String name; + // private final ArgumentType type; + // private SuggestionProvider suggestionsProvider = null; + name: String, + type_: dyn ArgumentType, + suggestions_provider: Option>, + + pub base: BaseArgumentBuilder, +} + +impl RequiredArgumentBuilder { + pub fn new(name: String, type_: dyn ArgumentType) -> Self { + Self { + name, + type_, + suggestions_provider: None, + base: BaseArgumentBuilder::new(name, type_), + } + } + + pub fn argument(name: String, type_: dyn ArgumentType) -> Self { + Self::new(name, type_) + } + + pub fn suggests(mut self, provider: dyn SuggestionProvider) -> Self { + self.suggestions_provider = Some(provider); + self + } + + pub fn suggestions_provider(&self) -> Option<&dyn SuggestionProvider> { + self.suggestions_provider.as_ref() + } + + pub fn get_type(&self) -> &dyn ArgumentType { + &self.type_ + } + + pub fn name(&self) -> &str { + &self.name + } + + // final ArgumentCommandNode result = new ArgumentCommandNode<>(getName(), getType(), getCommand(), getRequirement(), getRedirect(), getRedirectModifier(), isFork(), getSuggestionsProvider()); + + // for (final CommandNode argument : getArguments()) { + // result.addChild(argument); + // } + + // return result; + pub fn build(self) -> ArgumentCommandNode { + let result = ArgumentCommandNode { + name: self.name, + type_: &self.type_, + base: BaseCommandNode { + command: self.base.command, + requirement: self.base.requirement, + redirect: self.base.redirect, + modifier: self.base.modifier, + forks: self.base.forks, + ..BaseCommandNode::default() + }, + custom_suggestions: self.base.custom_suggestions, + }; + + for argument in self.base.arguments { + result.add_child(argument); + } + + result + } +} diff --git a/azalea-brigadier/src/command_dispatcher.rs b/azalea-brigadier/src/command_dispatcher.rs index c476a39b..0e9b9036 100644 --- a/azalea-brigadier/src/command_dispatcher.rs +++ b/azalea-brigadier/src/command_dispatcher.rs @@ -1,3 +1,5 @@ +use crate::tree::root_command_node::RootCommandNode; + /// The core command dispatcher, for registering, parsing, and executing commands. /// The `S` generic is a custom "source" type, such as a user or originator of a command pub struct CommandDispatcher { diff --git a/azalea-brigadier/src/context/command_context.rs b/azalea-brigadier/src/context/command_context.rs index c6210a88..7a2189d9 100644 --- a/azalea-brigadier/src/context/command_context.rs +++ b/azalea-brigadier/src/context/command_context.rs @@ -3,7 +3,9 @@ use super::{ string_range::StringRange, }; use crate::{ - arguments::argument_type::ArgumentType, command::Command, redirect_modifier::RedirectModifier, + arguments::argument_type::{ArgumentResult, ArgumentType}, + command::Command, + redirect_modifier::RedirectModifier, tree::command_node::CommandNode, }; use std::collections::HashMap; @@ -12,7 +14,7 @@ pub struct CommandContext { source: S, input: String, command: dyn Command, - arguments: HashMap>, + arguments: HashMap>>, root_node: dyn CommandNode, nodes: Vec>, range: StringRange, diff --git a/azalea-brigadier/src/context/command_context_builder.rs b/azalea-brigadier/src/context/command_context_builder.rs index e74b5b1c..ac4a36bb 100644 --- a/azalea-brigadier/src/context/command_context_builder.rs +++ b/azalea-brigadier/src/context/command_context_builder.rs @@ -1,8 +1,10 @@ use std::collections::HashMap; use crate::{ - arguments::argument_type::ArgumentType, command::Command, - command_dispatcher::CommandDispatcher, redirect_modifier::RedirectModifier, + arguments::argument_type::{ArgumentResult, ArgumentType}, + command::Command, + command_dispatcher::CommandDispatcher, + redirect_modifier::RedirectModifier, tree::command_node::CommandNode, }; @@ -26,7 +28,7 @@ use super::{ #[derive(Clone)] pub struct CommandContextBuilder { - arguments: HashMap>, + arguments: HashMap>>, root_node: dyn CommandNode, nodes: Vec>, dispatcher: CommandDispatcher, @@ -77,13 +79,15 @@ impl CommandContextBuilder { pub fn with_argument( mut self, name: String, - argument: ParsedArgument, + argument: ParsedArgument>, ) -> Self { self.arguments.insert(name, argument); self } - pub fn arguments(&self) -> &HashMap> { + pub fn arguments( + &self, + ) -> &HashMap>> { &self.arguments } diff --git a/azalea-brigadier/src/context/parsed_argument.rs b/azalea-brigadier/src/context/parsed_argument.rs index 5f9c2cdb..77a47078 100644 --- a/azalea-brigadier/src/context/parsed_argument.rs +++ b/azalea-brigadier/src/context/parsed_argument.rs @@ -1,12 +1,14 @@ +use std::marker::PhantomData; + use super::string_range::StringRange; #[derive(PartialEq, Eq, Hash)] -pub struct ParsedArgument { +pub struct ParsedArgument { range: StringRange, result: T, } -impl ParsedArgument { +impl ParsedArgument { fn new(start: usize, end: usize, result: T) -> Self { Self { range: StringRange::between(start, end), diff --git a/azalea-brigadier/src/tree/argument_command_node.rs b/azalea-brigadier/src/tree/argument_command_node.rs index df7d3f5c..51add3d5 100644 --- a/azalea-brigadier/src/tree/argument_command_node.rs +++ b/azalea-brigadier/src/tree/argument_command_node.rs @@ -1,7 +1,8 @@ use std::fmt::{Display, Formatter}; use crate::{ - arguments::argument_type::ArgumentType, + arguments::argument_type::{ArgumentResult, ArgumentType}, + builder::required_argument_builder::RequiredArgumentBuilder, context::{ command_context::CommandContext, command_context_builder::CommandContextBuilder, parsed_argument::ParsedArgument, @@ -22,14 +23,14 @@ const USAGE_ARGUMENT_CLOSE: &str = ">"; #[derive(Hash, PartialEq, Eq, Debug, Clone)] pub struct ArgumentCommandNode { name: String, - type_: dyn ArgumentType, + type_: Box>, custom_suggestions: dyn SuggestionProvider, // Since Rust doesn't have extending, we put the struct this is extending as the "base" field pub base: BaseCommandNode, } impl ArgumentCommandNode { - fn get_type(&self) -> &dyn ArgumentType { + fn get_type(&self) -> &dyn ArgumentType { &self.type_ } @@ -45,7 +46,7 @@ impl CommandNode for ArgumentCommandNode { fn parse( &self, - reader: StringReader, + reader: &mut StringReader, context_builder: CommandContextBuilder, ) -> Result<(), CommandSyntaxException> { // final int start = reader.getCursor(); @@ -68,7 +69,7 @@ impl CommandNode for ArgumentCommandNode { fn list_suggestions( &self, context: CommandContext, - builder: SuggestionsBuilder, + builder: &mut SuggestionsBuilder, ) -> Result { if self.custom_suggestions.is_none() { self.get_type().list_suggestions(context, builder) diff --git a/azalea-brigadier/src/tree/command_node.rs b/azalea-brigadier/src/tree/command_node.rs index 286820b9..717ea5f1 100644 --- a/azalea-brigadier/src/tree/command_node.rs +++ b/azalea-brigadier/src/tree/command_node.rs @@ -1,6 +1,7 @@ use std::collections::HashMap; use crate::{ + arguments::argument_type::{ArgumentResult, ArgumentType}, builder::argument_builder::ArgumentBuilder, command::Command, context::{command_context::CommandContext, command_context_builder::CommandContextBuilder}, @@ -13,17 +14,9 @@ use crate::{ use super::{argument_command_node::ArgumentCommandNode, literal_command_node::LiteralCommandNode}; pub struct BaseCommandNode { - // private final Map> children = new LinkedHashMap<>(); - // private final Map> literals = new LinkedHashMap<>(); - // private final Map> arguments = new LinkedHashMap<>(); - // private final Predicate requirement; - // private final CommandNode redirect; - // private final RedirectModifier modifier; - // private final boolean forks; - // private Command command; children: HashMap>, literals: HashMap>, - arguments: HashMap>, + arguments: HashMap>>, requirement: Option bool>, redirect: Option>, modifier: Option>,