aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormat <github@matdoes.dev>2022-01-11 00:01:47 -0600
committermat <github@matdoes.dev>2022-01-11 00:01:47 -0600
commitcc4fe62fc82842e0bde628437a45d55c6a82f1f3 (patch)
tree9248cb03406681f81d6d29a0878220fbe1e836e2
parent60b129b3a62b66dd389d1775892405fe735b9540 (diff)
downloadazalea-drasl-cc4fe62fc82842e0bde628437a45d55c6a82f1f3.tar.xz
adfsfasdfaSDQAWERTERYTUYghyubnjnrdfxcv etgvbhy0ujn-
-rw-r--r--azalea-brigadier/src/arguments/argument_type.rs6
-rw-r--r--azalea-brigadier/src/arguments/bool_argument_type.rs6
-rw-r--r--azalea-brigadier/src/context/command_context.rs11
-rw-r--r--azalea-brigadier/src/context/command_context_builder.rs2
-rw-r--r--azalea-brigadier/src/context/parsed_argument.rs2
-rw-r--r--azalea-brigadier/src/context/parsed_command_node.rs9
-rw-r--r--azalea-brigadier/src/context/string_range.rs2
-rw-r--r--azalea-brigadier/src/message.rs1
-rw-r--r--azalea-brigadier/src/suggestion/suggestion.rs90
-rw-r--r--azalea-brigadier/src/suggestion/suggestions.rs58
-rw-r--r--azalea-brigadier/src/suggestion/suggestions_builder.rs115
-rw-r--r--azalea-brigadier/src/tree/argument_command_node.rs23
-rw-r--r--azalea-brigadier/src/tree/command_node.rs2
-rw-r--r--azalea-brigadier/src/tree/root_command_node.rs1
14 files changed, 299 insertions, 29 deletions
diff --git a/azalea-brigadier/src/arguments/argument_type.rs b/azalea-brigadier/src/arguments/argument_type.rs
index 107b1cbf..46026735 100644
--- a/azalea-brigadier/src/arguments/argument_type.rs
+++ b/azalea-brigadier/src/arguments/argument_type.rs
@@ -7,7 +7,9 @@ use crate::{
};
pub trait Types {
- fn bool(value: bool) -> Self;
+ fn bool(value: bool) -> Self
+ where
+ Self: Sized;
}
/*
@@ -28,7 +30,7 @@ enum BrigadierTypes {
pub trait ArgumentType<T>
where
Self: Sized,
- T: Types,
+ T: Types + ?Sized,
{
// T parse(StringReader reader) throws CommandSyntaxException;
diff --git a/azalea-brigadier/src/arguments/bool_argument_type.rs b/azalea-brigadier/src/arguments/bool_argument_type.rs
index dc2c6896..1237caa0 100644
--- a/azalea-brigadier/src/arguments/bool_argument_type.rs
+++ b/azalea-brigadier/src/arguments/bool_argument_type.rs
@@ -33,13 +33,13 @@ where
// builder.suggest("false");
// }
// return builder.buildFuture();
- if "true".starts_with(builder.get_remaining_lower_case()) {
+ if "true".starts_with(builder.remaining_lowercase()) {
builder.suggest("true");
}
- if "false".starts_with(builder.get_remaining_lower_case()) {
+ if "false".starts_with(builder.remaining_lowercase()) {
builder.suggest("false");
}
- Ok(builder.build_future())
+ Ok(builder.build())
}
fn get_examples(&self) -> Vec<String> {
diff --git a/azalea-brigadier/src/context/command_context.rs b/azalea-brigadier/src/context/command_context.rs
index 36741906..68144a40 100644
--- a/azalea-brigadier/src/context/command_context.rs
+++ b/azalea-brigadier/src/context/command_context.rs
@@ -14,17 +14,20 @@ pub struct CommandContext<'a, S, T> {
command: &'a dyn Command<S, T>,
arguments: HashMap<String, ParsedArgument<T>>,
root_node: &'a dyn CommandNode<S, T>,
- nodes: Vec<ParsedCommandNode<'a, S, T>>,
+ nodes: Vec<ParsedCommandNode<S, T>>,
range: StringRange,
- child: Option<CommandContext<'a, S, T>>,
+ child: Option<&'a CommandContext<'a, S, T>>,
modifier: Option<&'a dyn RedirectModifier<S, T>>,
forks: bool,
}
-impl<S, T> CommandContext<'_, S, T> {
+impl<S, T> CommandContext<'_, S, T>
+where
+ S: PartialEq,
+{
pub fn clone_for(&self, source: S) -> Self {
if self.source == source {
- return self.clone();
+ return *self;
}
Self {
source,
diff --git a/azalea-brigadier/src/context/command_context_builder.rs b/azalea-brigadier/src/context/command_context_builder.rs
index 878d7692..88e26343 100644
--- a/azalea-brigadier/src/context/command_context_builder.rs
+++ b/azalea-brigadier/src/context/command_context_builder.rs
@@ -28,7 +28,7 @@ use super::{
pub struct CommandContextBuilder<'a, S, T> {
arguments: HashMap<String, ParsedArgument<T>>,
root_node: &'a dyn CommandNode<S, T>,
- nodes: Vec<ParsedCommandNode<'a, S, T>>,
+ nodes: Vec<ParsedCommandNode<S, T>>,
dispatcher: CommandDispatcher<'a, S, T>,
source: S,
command: Box<dyn Command<S, T>>,
diff --git a/azalea-brigadier/src/context/parsed_argument.rs b/azalea-brigadier/src/context/parsed_argument.rs
index 75c07784..447a1223 100644
--- a/azalea-brigadier/src/context/parsed_argument.rs
+++ b/azalea-brigadier/src/context/parsed_argument.rs
@@ -1,6 +1,6 @@
use super::string_range::StringRange;
-#[derive(PartialEq, Eq, Hash)]
+#[derive(PartialEq, Eq, Hash, Clone)]
pub struct ParsedArgument<T> {
range: StringRange,
// T is an item in an enum
diff --git a/azalea-brigadier/src/context/parsed_command_node.rs b/azalea-brigadier/src/context/parsed_command_node.rs
index a006aa4b..14168a06 100644
--- a/azalea-brigadier/src/context/parsed_command_node.rs
+++ b/azalea-brigadier/src/context/parsed_command_node.rs
@@ -1,14 +1,13 @@
use super::string_range::StringRange;
use crate::tree::command_node::CommandNode;
-#[derive(Hash, PartialEq, Eq, Debug, Clone)]
-pub struct ParsedCommandNode<'a, S, T> {
- node: &'a dyn CommandNode<S, T>,
+pub struct ParsedCommandNode<S, T> {
+ node: Box<dyn CommandNode<S, T>>,
range: StringRange,
}
-impl<S, T> ParsedCommandNode<'_, S, T> {
- fn new(node: &dyn CommandNode<S, T>, range: StringRange) -> Self {
+impl<S, T> ParsedCommandNode<S, T> {
+ fn new(node: dyn CommandNode<S, T>, range: StringRange) -> Self {
Self { node, range }
}
diff --git a/azalea-brigadier/src/context/string_range.rs b/azalea-brigadier/src/context/string_range.rs
index d775ab68..87098a1a 100644
--- a/azalea-brigadier/src/context/string_range.rs
+++ b/azalea-brigadier/src/context/string_range.rs
@@ -1,6 +1,6 @@
use std::cmp;
-#[derive(Debug, Clone, PartialEq, Eq)]
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct StringRange {
start: usize,
end: usize,
diff --git a/azalea-brigadier/src/message.rs b/azalea-brigadier/src/message.rs
index 71d0b178..42894d0e 100644
--- a/azalea-brigadier/src/message.rs
+++ b/azalea-brigadier/src/message.rs
@@ -1,5 +1,6 @@
use std::rc::Rc;
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct Message(Rc<String>);
impl Message {
diff --git a/azalea-brigadier/src/suggestion/suggestion.rs b/azalea-brigadier/src/suggestion/suggestion.rs
index e69de29b..4cbed7be 100644
--- a/azalea-brigadier/src/suggestion/suggestion.rs
+++ b/azalea-brigadier/src/suggestion/suggestion.rs
@@ -0,0 +1,90 @@
+use std::cmp;
+
+use crate::{context::string_range::StringRange, message::Message};
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub struct Suggestion {
+ range: StringRange,
+ text: String,
+ tooltip: Option<Message>,
+}
+
+impl Suggestion {
+ pub fn new(range: StringRange, text: String) -> Suggestion {
+ Suggestion {
+ range,
+ text,
+ tooltip: None,
+ }
+ }
+
+ pub fn new_with_tooltip(range: StringRange, text: String, tooltip: Message) -> Suggestion {
+ Suggestion {
+ range,
+ text,
+ tooltip: Some(tooltip),
+ }
+ }
+
+ pub fn range(&self) -> &StringRange {
+ &self.range
+ }
+
+ pub fn text(&self) -> &String {
+ &self.text
+ }
+
+ pub fn tooltip(&self) -> Option<&Message> {
+ self.tooltip.as_ref()
+ }
+
+ pub fn apply(&self, input: &str) -> String {
+ if self.range.start() == 0 && self.range.end() == input.len() {
+ return self.text.clone();
+ }
+ let mut result = String::new();
+ if self.range.start() > 0 {
+ result.push_str(&input[0..self.range.start()]);
+ }
+ result.push_str(&self.text);
+ if self.range.end() < input.len() {
+ result.push_str(&input[self.range.end()..]);
+ }
+ result
+ }
+
+ pub fn expand(&self, command: &str, range: StringRange) -> Suggestion {
+ if range == self.range {
+ return self.clone();
+ }
+ let mut result = String::new();
+ if range.start() < self.range.start() {
+ result.push_str(&command[range.start()..self.range.start()]);
+ }
+ result.push_str(&self.text);
+ if range.end() > self.range.end() {
+ result.push_str(&command[self.range.end()..range.end()]);
+ }
+ Suggestion {
+ range,
+ text: result,
+ tooltip: self.tooltip.clone(),
+ }
+ }
+
+ pub fn compare_ignore_case(&self, b: &Suggestion) -> cmp::Ordering {
+ self.text.to_lowercase().cmp(&b.text.to_lowercase())
+ }
+}
+
+impl PartialOrd for Suggestion {
+ fn partial_cmp(&self, other: &Suggestion) -> Option<cmp::Ordering> {
+ Some(self.text.cmp(&other.text))
+ }
+}
+
+impl Ord for Suggestion {
+ fn cmp(&self, other: &Suggestion) -> cmp::Ordering {
+ self.text.cmp(&other.text)
+ }
+}
diff --git a/azalea-brigadier/src/suggestion/suggestions.rs b/azalea-brigadier/src/suggestion/suggestions.rs
index 354fc418..18572d20 100644
--- a/azalea-brigadier/src/suggestion/suggestions.rs
+++ b/azalea-brigadier/src/suggestion/suggestions.rs
@@ -1 +1,59 @@
+use std::cmp;
+
+use crate::{context::string_range::StringRange, message::Message};
+
pub struct Suggestions {}
+
+// #[cfg(test)]
+// mod tests {
+// use crate::suggestion::suggestion::Suggestion;
+
+// use super::*;
+
+// #[test]
+// fn merge_empty() {
+// let merged = Suggestions::merge("foo b", vec![]);
+// assert_eq!(merged.is_empty(), true);
+// }
+
+// #[test]
+// fn merge_single() {
+// let suggestions = Suggestions::new(StringRange::at(5), "ar".to_string());
+// let merged = Suggestions::merge("foo b", vec![suggestions]);
+// assert_eq!(merged, suggestions);
+// }
+
+// #[test]
+// fn merge_multiple() {
+// let a = Suggestions::new(
+// StringRange::at(5),
+// vec![
+// Suggestion::new(StringRange::at(5), "ar".to_string()),
+// Suggestion::new(StringRange::at(5), "az".to_string()),
+// Suggestion::new(StringRange::at(5), "Az".to_string()),
+// ],
+// );
+// let b = Suggestions::new(
+// StringRange::between(4, 5),
+// vec![
+// Suggestion::new(StringRange::between(4, 5), "foo".to_string()),
+// Suggestion::new(StringRange::between(4, 5), "qux".to_string()),
+// Suggestion::new(StringRange::between(4, 5), "apple".to_string()),
+// Suggestion::new(StringRange::between(4, 5), "Bar".to_string()),
+// ],
+// );
+// let merged = Suggestions::merge("foo b", vec![a, b]);
+// assert_eq!(
+// merged.get_list(),
+// vec![
+// Suggestion::new(StringRange::between(4, 5), "apple".to_string()),
+// Suggestion::new(StringRange::between(4, 5), "bar".to_string()),
+// Suggestion::new(StringRange::between(4, 5), "Bar".to_string()),
+// Suggestion::new(StringRange::between(4, 5), "baz".to_string()),
+// Suggestion::new(StringRange::between(4, 5), "bAz".to_string()),
+// Suggestion::new(StringRange::between(4, 5), "foo".to_string()),
+// Suggestion::new(StringRange::between(4, 5), "qux".to_string()),
+// ]
+// );
+// }
+// }
diff --git a/azalea-brigadier/src/suggestion/suggestions_builder.rs b/azalea-brigadier/src/suggestion/suggestions_builder.rs
index 6960f52b..7853a3a2 100644
--- a/azalea-brigadier/src/suggestion/suggestions_builder.rs
+++ b/azalea-brigadier/src/suggestion/suggestions_builder.rs
@@ -1 +1,114 @@
-pub struct SuggestionsBuilder {}
+use crate::context::string_range::StringRange;
+
+use super::{suggestion::Suggestion, suggestions::Suggestions};
+
+pub struct SuggestionsBuilder {
+ input: String,
+ input_lowercase: String,
+ start: usize,
+ remaining: String,
+ remaining_lowercase: String,
+ result: Vec<Suggestion>,
+}
+
+impl SuggestionsBuilder {
+ pub fn new_with_lowercase(
+ input: String,
+ input_lowercase: String,
+ start: usize,
+ ) -> SuggestionsBuilder {
+ SuggestionsBuilder {
+ input,
+ input_lowercase,
+ start,
+ remaining: input.get(start..).unwrap().to_string(),
+ remaining_lowercase: input_lowercase.get(start..).unwrap().to_string(),
+ result: Vec::new(),
+ }
+ }
+
+ pub fn new(input: String, start: usize) -> SuggestionsBuilder {
+ SuggestionsBuilder::new_with_lowercase(input, input.to_lowercase(), start)
+ }
+
+ pub fn input(&self) -> &str {
+ &self.input
+ }
+
+ pub fn start(&self) -> usize {
+ self.start
+ }
+
+ pub fn remaining(&self) -> &str {
+ &self.remaining
+ }
+
+ pub fn remaining_lowercase(&self) -> &str {
+ &self.remaining_lowercase
+ }
+
+ pub fn build(&self) -> Suggestions {
+ Suggestions::create(self.input(), self.result)
+ }
+
+ pub fn suggest(&mut self, text: &str) -> &mut SuggestionsBuilder {
+ if text == self.remaining {
+ return self;
+ }
+ self.result.push(Suggestion::new(
+ StringRange::between(self.start, self.input.len()),
+ text,
+ ));
+ self
+ }
+
+ pub fn suggest_with_tooltip(&mut self, text: &str, tooltip: &str) -> &mut SuggestionsBuilder {
+ if text == self.remaining {
+ return self;
+ }
+ self.result.push(Suggestion::new_with_tooltip(
+ StringRange::between(self.start, self.input.len()),
+ text,
+ tooltip,
+ ));
+ self
+ }
+
+ pub fn suggest_with_value(&mut self, value: i32) -> &mut SuggestionsBuilder {
+ self.result.push(IntegerSuggestion::new(
+ StringRange::between(self.start, self.input.len()),
+ value,
+ ));
+ self
+ }
+
+ pub fn suggest_with_value_and_tooltip(
+ &mut self,
+ value: i32,
+ tooltip: &str,
+ ) -> &mut SuggestionsBuilder {
+ self.result.push(IntegerSuggestion::new_with_tooltip(
+ StringRange::between(self.start, self.input.len()),
+ value,
+ tooltip,
+ ));
+ self
+ }
+
+ pub fn add(&mut self, other: &SuggestionsBuilder) -> &mut SuggestionsBuilder {
+ self.result.extend(other.result.iter().cloned());
+ self
+ }
+
+ pub fn create_offset(&self, start: usize) -> SuggestionsBuilder {
+ SuggestionsBuilder::new_with_lowercase(
+ self.input.clone(),
+ self.input_lowercase.clone(),
+ start,
+ )
+ }
+
+ pub fn restart(&self) -> SuggestionsBuilder {
+ self.create_offset(self.start)
+ }
+}
diff --git a/azalea-brigadier/src/tree/argument_command_node.rs b/azalea-brigadier/src/tree/argument_command_node.rs
index 4d38b41f..647b6c35 100644
--- a/azalea-brigadier/src/tree/argument_command_node.rs
+++ b/azalea-brigadier/src/tree/argument_command_node.rs
@@ -1,13 +1,14 @@
use std::fmt::{Display, Formatter};
use crate::{
- arguments::argument_type::ArgumentType,
+ arguments::argument_type::{ArgumentType, Types},
builder::required_argument_builder::RequiredArgumentBuilder,
context::{
command_context::CommandContext, command_context_builder::CommandContextBuilder,
parsed_argument::ParsedArgument,
},
exceptions::command_syntax_exception::CommandSyntaxException,
+ immutable_string_reader::ImmutableStringReader,
string_reader::StringReader,
suggestion::{
suggestion_provider::SuggestionProvider, suggestions::Suggestions,
@@ -20,11 +21,15 @@ 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<'a, S, T> {
+pub struct ArgumentCommandNode<'a, S, T>
+where
+ // each argument command node has its own different type
+ T: ArgumentType<dyn Types>,
+{
name: String,
type_: &'a T,
- custom_suggestions: &'a dyn SuggestionProvider<S, T>,
+ custom_suggestions: Option<&'a dyn SuggestionProvider<S, T>>,
+ // custom_suggestions: &'a dyn SuggestionProvider<S, T>,
// Since Rust doesn't have extending, we put the struct this is extending as the "base" field
pub base: BaseCommandNode<'a, S, T>,
}
@@ -34,12 +39,12 @@ impl<S, T> ArgumentCommandNode<'_, S, T> {
&self.type_
}
- fn custom_suggestions(&self) -> &dyn SuggestionProvider<S, T> {
- &self.custom_suggestions
+ fn custom_suggestions(&self) -> Option<&dyn SuggestionProvider<S, T>> {
+ self.custom_suggestions
}
}
-impl<S, T> CommandNode<S, T> for ArgumentCommandNode<'_, S, T> {
+impl<'a, S, T> CommandNode<S, T> for ArgumentCommandNode<'a, S, T> {
fn name(&self) -> &str {
&self.name
}
@@ -56,7 +61,7 @@ impl<S, T> CommandNode<S, T> for ArgumentCommandNode<'_, S, T> {
// contextBuilder.withArgument(name, parsed);
// contextBuilder.withNode(this, parsed.getRange());
- let start = reader.get_cursor();
+ let start = reader.cursor();
let result = self.get_type().parse(reader)?;
let parsed = ParsedArgument::new(start, reader.get_cursor(), result);
@@ -112,7 +117,7 @@ impl<S, T> CommandNode<S, T> for ArgumentCommandNode<'_, S, T> {
}
}
-impl Display for ArgumentCommandNode<'_, String, String> {
+impl Display for ArgumentCommandNode<'_, (), (), ()> {
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 bcba9c03..8e262f0b 100644
--- a/azalea-brigadier/src/tree/command_node.rs
+++ b/azalea-brigadier/src/tree/command_node.rs
@@ -31,7 +31,7 @@ pub trait CommandNode<S, T> {
fn usage_text(&self) -> &str;
fn parse(
&self,
- reader: StringReader,
+ reader: &mut StringReader,
context_builder: CommandContextBuilder<S, T>,
) -> Result<(), CommandSyntaxException>;
fn list_suggestions(
diff --git a/azalea-brigadier/src/tree/root_command_node.rs b/azalea-brigadier/src/tree/root_command_node.rs
index 25a5a4b2..36787340 100644
--- a/azalea-brigadier/src/tree/root_command_node.rs
+++ b/azalea-brigadier/src/tree/root_command_node.rs
@@ -11,7 +11,6 @@ use crate::{
use super::command_node::{BaseCommandNode, CommandNode};
-#[derive(Hash, PartialEq, Eq, Debug, Clone)]
pub struct RootCommandNode<'a, S, T> {
// Since Rust doesn't have extending, we put the struct this is extending as the "base" field
pub base: BaseCommandNode<'a, S, T>,