diff options
| author | mat <github@matdoes.dev> | 2022-01-09 22:33:45 -0600 |
|---|---|---|
| committer | mat <github@matdoes.dev> | 2022-01-09 22:33:45 -0600 |
| commit | 315f2258190b33c63df7797a97178019f5aea02b (patch) | |
| tree | 1ec5f467e7bd42f7aed3aaadbcbc226f8a6ce4f2 /azalea-brigadier/src/tree | |
| parent | d56f60c05f316ab4cc37ebe7a9ad4caf91a75de6 (diff) | |
| download | azalea-drasl-315f2258190b33c63df7797a97178019f5aea02b.tar.xz | |
add some more stuff from brigadier
Diffstat (limited to 'azalea-brigadier/src/tree')
| -rw-r--r-- | azalea-brigadier/src/tree/argument_command_node.rs | 118 | ||||
| -rw-r--r-- | azalea-brigadier/src/tree/command_node.rs | 52 | ||||
| -rw-r--r-- | azalea-brigadier/src/tree/literal_command_node.rs | 96 | ||||
| -rw-r--r-- | azalea-brigadier/src/tree/mod.rs | 4 | ||||
| -rw-r--r-- | azalea-brigadier/src/tree/root_command_node.rs | 61 |
5 files changed, 331 insertions, 0 deletions
diff --git a/azalea-brigadier/src/tree/argument_command_node.rs b/azalea-brigadier/src/tree/argument_command_node.rs index e69de29b..df7d3f5c 100644 --- a/azalea-brigadier/src/tree/argument_command_node.rs +++ b/azalea-brigadier/src/tree/argument_command_node.rs @@ -0,0 +1,118 @@ +use std::fmt::{Display, Formatter}; + +use crate::{ + arguments::argument_type::ArgumentType, + context::{ + command_context::CommandContext, command_context_builder::CommandContextBuilder, + parsed_argument::ParsedArgument, + }, + exceptions::command_syntax_exception::CommandSyntaxException, + string_reader::StringReader, + suggestion::{ + suggestion_provider::SuggestionProvider, suggestions::Suggestions, + suggestions_builder::SuggestionsBuilder, + }, +}; + +use super::command_node::{BaseCommandNode, CommandNode}; + +const USAGE_ARGUMENT_OPEN: &str = "<"; +const USAGE_ARGUMENT_CLOSE: &str = ">"; + +#[derive(Hash, PartialEq, Eq, Debug, Clone)] +pub struct ArgumentCommandNode<S, T> { + name: String, + type_: dyn ArgumentType, + custom_suggestions: dyn SuggestionProvider<S>, + // Since Rust doesn't have extending, we put the struct this is extending as the "base" field + pub base: BaseCommandNode<S>, +} + +impl<S, T> ArgumentCommandNode<S, T> { + fn get_type(&self) -> &dyn ArgumentType { + &self.type_ + } + + fn custom_suggestions(&self) -> &dyn SuggestionProvider<S> { + &self.custom_suggestions + } +} + +impl<S, T> CommandNode<S> for ArgumentCommandNode<S, T> { + fn name(&self) -> &str { + &self.name + } + + fn parse( + &self, + reader: StringReader, + context_builder: CommandContextBuilder<S>, + ) -> Result<(), CommandSyntaxException> { + // final int start = reader.getCursor(); + // final T result = type.parse(reader); + // final ParsedArgument<S, T> parsed = new ParsedArgument<>(start, reader.getCursor(), result); + + // contextBuilder.withArgument(name, parsed); + // contextBuilder.withNode(this, parsed.getRange()); + + let start = reader.get_cursor(); + let result = self.get_type().parse(reader)?; + let parsed = ParsedArgument::new(start, reader.get_cursor(), result); + + context_builder.with_argument(&self.name, parsed); + context_builder.with_node(self, parsed.get_range()); + + Ok(()) + } + + fn list_suggestions( + &self, + context: CommandContext<S>, + builder: SuggestionsBuilder, + ) -> Result<Suggestions, CommandSyntaxException> { + if self.custom_suggestions.is_none() { + self.get_type().list_suggestions(context, builder) + } else { + self.custom_suggestions.get_suggestions(context, builder) + } + } + + fn is_valid_input(&self, input: &str) -> bool { + let reader = StringReader::new(input); + let result = self.get_type().parse(reader); + if result.is_ok() { + return !reader.can_read() || reader.peek() == ' '; + } else { + return false; + } + } + + fn usage_text(&self) -> &str { + USAGE_ARGUMENT_OPEN + self.name + USAGE_ARGUMENT_CLOSE + } + + fn create_builder(&self) -> RequiredArgumentBuilder<S, T> { + let builder = RequiredArgumentBuilder::argument(&self.name, &self.type_); + builder.requires(self.base.get_requirement()); + builder.forward( + self.base.get_redirect(), + self.base.get_redirect_modifier(), + self.base.is_fork(), + ); + builder.suggests(self.custom_suggestions()); + if self.base.get_command() != None { + builder.executes(self.base.get_command().unwrap()); + } + builder + } + + fn get_examples(&self) -> Vec<String> { + self.type_.get_examples() + } +} + +impl Display for ArgumentCommandNode<String, String> { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "<argument {}: {}>", self.name, self.type_) + } +} diff --git a/azalea-brigadier/src/tree/command_node.rs b/azalea-brigadier/src/tree/command_node.rs index e69de29b..286820b9 100644 --- a/azalea-brigadier/src/tree/command_node.rs +++ b/azalea-brigadier/src/tree/command_node.rs @@ -0,0 +1,52 @@ +use std::collections::HashMap; + +use crate::{ + builder::argument_builder::ArgumentBuilder, + command::Command, + context::{command_context::CommandContext, command_context_builder::CommandContextBuilder}, + exceptions::command_syntax_exception::CommandSyntaxException, + redirect_modifier::RedirectModifier, + string_reader::StringReader, + suggestion::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder}, +}; + +use super::{argument_command_node::ArgumentCommandNode, literal_command_node::LiteralCommandNode}; + +pub struct BaseCommandNode<S> { + // private final Map<String, CommandNode<S>> children = new LinkedHashMap<>(); + // private final Map<String, LiteralCommandNode<S>> literals = new LinkedHashMap<>(); + // private final Map<String, ArgumentCommandNode<S, ?>> arguments = new LinkedHashMap<>(); + // private final Predicate<S> requirement; + // private final CommandNode<S> redirect; + // private final RedirectModifier<S> modifier; + // private final boolean forks; + // private Command<S> command; + children: HashMap<String, dyn CommandNode<S>>, + literals: HashMap<String, LiteralCommandNode<S>>, + arguments: HashMap<String, ArgumentCommandNode<S, _>>, + requirement: Option<dyn Fn(&S) -> bool>, + redirect: Option<dyn CommandNode<S>>, + modifier: Option<dyn RedirectModifier<S>>, + forks: bool, + command: Option<dyn Command<S>>, +} + +impl<S> BaseCommandNode<S> {} + +pub trait CommandNode<S> { + fn name(&self) -> &str; + fn usage_text(&self) -> &str; + fn parse( + &self, + reader: StringReader, + context_builder: CommandContextBuilder<S>, + ) -> Result<(), CommandSyntaxException>; + fn list_suggestions( + &self, + context: CommandContext<S>, + builder: SuggestionsBuilder, + ) -> Result<Suggestions, CommandSyntaxException>; + fn is_valid_input(&self, input: &str) -> bool; + fn create_builder<T>(&self) -> dyn ArgumentBuilder<S, T>; + fn get_examples(&self) -> Vec<String>; +} diff --git a/azalea-brigadier/src/tree/literal_command_node.rs b/azalea-brigadier/src/tree/literal_command_node.rs index e69de29b..bb0e613c 100644 --- a/azalea-brigadier/src/tree/literal_command_node.rs +++ b/azalea-brigadier/src/tree/literal_command_node.rs @@ -0,0 +1,96 @@ +use crate::{ + context::{command_context::CommandContext, command_context_builder::CommandContextBuilder}, + exceptions::{ + builtin_exceptions::BuiltInExceptions, command_syntax_exception::CommandSyntaxException, + }, + string_reader::StringReader, + suggestion::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder}, +}; + +use super::command_node::{BaseCommandNode, CommandNode}; + +#[derive(Hash, PartialEq, Eq, Debug, Clone)] +pub struct LiteralCommandNode<S> { + literal: String, + literal_lowercase: String, + // Since Rust doesn't have extending, we put the struct this is extending as the "base" field + pub base: BaseCommandNode<S>, +} + +impl<S> LiteralCommandNode<S> { + pub fn literal(&self) -> &String { + &self.literal + } + + pub fn parse(&self, reader: StringReader) -> i32 { + let start = reader.get_cursor(); + if reader.can_read(self.literal.len()) { + let end = start + self.literal.len(); + if reader.get_string()[start..end].eq(&self.literal) { + reader.set_cursor(end); + if !reader.can_read() || reader.peek() == ' ' { + return end as i32; + } else { + reader.set_cursor(start); + } + } + } + -1 + } +} + +impl<S> CommandNode<S> for LiteralCommandNode<S> { + fn name(&self) -> &str { + &self.literal + } + + fn parse( + &self, + reader: StringReader, + context_builder: CommandContextBuilder<S>, + ) -> Result<(), CommandSyntaxException> { + let start = reader.get_cursor(); + let end = self.parse(reader); + if end > -1 { + return Ok(()); + } + + Err(BuiltInExceptions::LiteralIncorrect { + expected: self.literal(), + } + .create_with_context(reader)) + } + + fn list_suggestions( + &self, + context: CommandContext<S>, + builder: SuggestionsBuilder, + ) -> Result<Suggestions, CommandSyntaxException> { + if self + .literal_lowercase + .starts_with(&builder.remaining_lowercase()) + { + builder.suggest(self.literal()) + } else { + Suggestions::empty() + } + } + + fn is_valid_input(&self, input: &str) -> bool { + self.parse(StringReader::from(input)) > -1 + } + + fn usage_text(&self) -> &str { + self.literal + } + + fn create_builder(&self) -> LiteralArgumentBuilder<S> { + let builder = LiteralArgumentBuilder::literal(self.literal()); + builder.requires(self.requirement()); + builder.forward(self.redirect(), self.redirect_modifier(), self.is_fork()); + if self.command().is_some() { + builder.executes(self.command().unwrap()); + } + builder + } +} diff --git a/azalea-brigadier/src/tree/mod.rs b/azalea-brigadier/src/tree/mod.rs index e69de29b..3dc22583 100644 --- a/azalea-brigadier/src/tree/mod.rs +++ b/azalea-brigadier/src/tree/mod.rs @@ -0,0 +1,4 @@ +pub mod argument_command_node; +pub mod command_node; +pub mod literal_command_node; +pub mod root_command_node; diff --git a/azalea-brigadier/src/tree/root_command_node.rs b/azalea-brigadier/src/tree/root_command_node.rs index e69de29b..004ab6a8 100644 --- a/azalea-brigadier/src/tree/root_command_node.rs +++ b/azalea-brigadier/src/tree/root_command_node.rs @@ -0,0 +1,61 @@ +use std::fmt::{Display, Formatter}; + +use crate::{ + context::{command_context::CommandContext, command_context_builder::CommandContextBuilder}, + exceptions::{ + builtin_exceptions::BuiltInExceptions, command_syntax_exception::CommandSyntaxException, + }, + string_reader::StringReader, + suggestion::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder}, +}; + +use super::command_node::{BaseCommandNode, CommandNode}; + +#[derive(Hash, PartialEq, Eq, Debug, Clone)] +pub struct RootCommandNode<S> { + // Since Rust doesn't have extending, we put the struct this is extending as the "base" field + pub base: BaseCommandNode<S>, +} + +impl<S> CommandNode<S> for RootCommandNode<S> { + fn name(&self) -> &str { + "" + } + + fn parse( + &self, + reader: StringReader, + context_builder: CommandContextBuilder<S>, + ) -> Result<(), CommandSyntaxException> { + } + + fn list_suggestions( + &self, + context: CommandContext<S>, + builder: SuggestionsBuilder, + ) -> Result<Suggestions, CommandSyntaxException> { + Suggestions::empty() + } + + fn is_valid_input(&self, input: &str) -> bool { + false + } + + fn usage_text(&self) -> &str { + "" + } + + fn create_builder(&self) -> () { + panic!("Cannot convert root into a builder"); + } + + fn get_examples(&self) -> Vec<String> { + vec![] + } +} + +impl Display for RootCommandNode<()> { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + write!(f, "<root>") + } +} |
