aboutsummaryrefslogtreecommitdiff
path: root/azalea-brigadier/src/context
diff options
context:
space:
mode:
authormat <github@matdoes.dev>2022-01-09 22:33:45 -0600
committermat <github@matdoes.dev>2022-01-09 22:33:45 -0600
commit315f2258190b33c63df7797a97178019f5aea02b (patch)
tree1ec5f467e7bd42f7aed3aaadbcbc226f8a6ce4f2 /azalea-brigadier/src/context
parentd56f60c05f316ab4cc37ebe7a9ad4caf91a75de6 (diff)
downloadazalea-drasl-315f2258190b33c63df7797a97178019f5aea02b.tar.xz
add some more stuff from brigadier
Diffstat (limited to 'azalea-brigadier/src/context')
-rw-r--r--azalea-brigadier/src/context/command_context.rs87
-rw-r--r--azalea-brigadier/src/context/command_context_builder.rs180
-rw-r--r--azalea-brigadier/src/context/parsed_argument.rs24
-rw-r--r--azalea-brigadier/src/context/parsed_command_node.rs22
-rw-r--r--azalea-brigadier/src/context/string_range.rs45
-rw-r--r--azalea-brigadier/src/context/suggestion_context.rs6
6 files changed, 364 insertions, 0 deletions
diff --git a/azalea-brigadier/src/context/command_context.rs b/azalea-brigadier/src/context/command_context.rs
index ddbb447e..c6210a88 100644
--- a/azalea-brigadier/src/context/command_context.rs
+++ b/azalea-brigadier/src/context/command_context.rs
@@ -1,3 +1,90 @@
+use super::{
+ parsed_argument::ParsedArgument, parsed_command_node::ParsedCommandNode,
+ string_range::StringRange,
+};
+use crate::{
+ arguments::argument_type::ArgumentType, command::Command, redirect_modifier::RedirectModifier,
+ tree::command_node::CommandNode,
+};
+use std::collections::HashMap;
+
pub struct CommandContext<S> {
source: S,
+ input: String,
+ command: dyn Command<S>,
+ arguments: HashMap<String, ParsedArgument<S, dyn ArgumentType>>,
+ root_node: dyn CommandNode<S>,
+ nodes: Vec<ParsedCommandNode<S>>,
+ range: StringRange,
+ child: Option<CommandContext<S>>,
+ modifier: Option<dyn RedirectModifier<S>>,
+ forks: bool,
+}
+
+impl<S> CommandContext<S> {
+ pub fn clone_for(&self, source: S) -> Self {
+ if self.source == source {
+ return self.clone();
+ }
+ Self {
+ source,
+ input: self.input.clone(),
+ command: self.command.clone(),
+ arguments: self.arguments.clone(),
+ root_node: self.root_node.clone(),
+ nodes: self.nodes.clone(),
+ range: self.range.clone(),
+ child: self.child.clone(),
+ modifier: self.modifier.clone(),
+ forks: self.forks,
+ }
+ }
+
+ fn child(&self) -> &Option<CommandContext<S>> {
+ &self.child
+ }
+
+ fn last_child(&self) -> &CommandContext<S> {
+ let mut result = self;
+ while result.child.is_some() {
+ result = result.child.as_ref().unwrap();
+ }
+ result
+ }
+
+ fn command(&self) -> &dyn Command<S> {
+ &self.command
+ }
+
+ fn source(&self) -> &S {
+ &self.source
+ }
+
+ // public <V> V getArgument(final String name, final Class<V> clazz) {
+ // final ParsedArgument<S, ?> argument = arguments.get(name);
+
+ // if (argument == null) {
+ // throw new IllegalArgumentException("No such argument '" + name + "' exists on this command");
+ // }
+
+ // final Object result = argument.getResult();
+ // if (PRIMITIVE_TO_WRAPPER.getOrDefault(clazz, clazz).isAssignableFrom(result.getClass())) {
+ // return (V) result;
+ // } else {
+ // throw new IllegalArgumentException("Argument '" + name + "' is defined as " + result.getClass().getSimpleName() + ", not " + clazz);
+ // }
+ // }
+ fn get_argument<V>(&self, name: &str) -> Result<V, String> {
+ let argument = self.arguments.get(name);
+
+ if argument.is_none() {
+ return Err(format!(
+ "No such argument '{}' exists on this command",
+ name
+ ));
+ }
+
+ let result = argument.unwrap().result();
+ Ok(result)
+ }
}
diff --git a/azalea-brigadier/src/context/command_context_builder.rs b/azalea-brigadier/src/context/command_context_builder.rs
index e69de29b..e74b5b1c 100644
--- a/azalea-brigadier/src/context/command_context_builder.rs
+++ b/azalea-brigadier/src/context/command_context_builder.rs
@@ -0,0 +1,180 @@
+use std::collections::HashMap;
+
+use crate::{
+ arguments::argument_type::ArgumentType, command::Command,
+ command_dispatcher::CommandDispatcher, redirect_modifier::RedirectModifier,
+ tree::command_node::CommandNode,
+};
+
+use super::{
+ command_context::CommandContext, parsed_argument::ParsedArgument,
+ parsed_command_node::ParsedCommandNode, string_range::StringRange,
+ suggestion_context::SuggestionContext,
+};
+
+// public class CommandContextBuilder<S> {
+// private final Map<String, ParsedArgument<S, ?>> arguments = new LinkedHashMap<>();
+// private final CommandNode<S> rootNode;
+// private final List<ParsedCommandNode<S>> nodes = new ArrayList<>();
+// private final CommandDispatcher<S> dispatcher;
+// private S source;
+// private Command<S> command;
+// private CommandContextBuilder<S> child;
+// private StringRange range;
+// private RedirectModifier<S> modifier = null;
+// private boolean forks;
+
+#[derive(Clone)]
+pub struct CommandContextBuilder<S> {
+ arguments: HashMap<String, ParsedArgument<S, dyn ArgumentType>>,
+ root_node: dyn CommandNode<S>,
+ nodes: Vec<ParsedCommandNode<S>>,
+ dispatcher: CommandDispatcher<S>,
+ source: S,
+ command: Box<dyn Command<S>>,
+ child: Option<CommandContextBuilder<S>>,
+ range: StringRange,
+ modifier: Option<Box<dyn RedirectModifier<S>>>,
+ forks: bool,
+}
+
+// public CommandContextBuilder(final CommandDispatcher<S> dispatcher, final S source, final CommandNode<S> rootNode, final int start) {
+// this.rootNode = rootNode;
+// this.dispatcher = dispatcher;
+// this.source = source;
+// this.range = StringRange.at(start);
+// }
+
+impl<S> CommandContextBuilder<S> {
+ pub fn new(
+ dispatcher: CommandDispatcher<S>,
+ source: S,
+ root_node: dyn CommandNode<S>,
+ start: usize,
+ ) -> Self {
+ Self {
+ root_node,
+ dispatcher,
+ source,
+ range: StringRange::at(start),
+ ..Default::default()
+ }
+ }
+
+ pub fn with_source(mut self, source: S) -> Self {
+ self.source = source;
+ self
+ }
+
+ pub fn source(&self) -> &S {
+ &self.source
+ }
+
+ pub fn root_node(&self) -> &dyn CommandNode<S> {
+ &self.root_node
+ }
+
+ pub fn with_argument(
+ mut self,
+ name: String,
+ argument: ParsedArgument<S, dyn ArgumentType>,
+ ) -> Self {
+ self.arguments.insert(name, argument);
+ self
+ }
+
+ pub fn arguments(&self) -> &HashMap<String, ParsedArgument<S, dyn ArgumentType>> {
+ &self.arguments
+ }
+
+ pub fn with_command(mut self, command: Box<dyn Command<S>>) -> Self {
+ self.command = command;
+ self
+ }
+
+ pub fn with_node(mut self, node: dyn CommandNode<S>, range: StringRange) -> Self {
+ self.nodes.push(ParsedCommandNode::new(node, range));
+ self.range = StringRange::encompassing(&self.range, &range);
+ self.modifier = node.redirect_modifier();
+ self.forks = node.is_fork();
+ self
+ }
+
+ pub fn with_child(mut self, child: CommandContextBuilder<S>) -> Self {
+ self.child = Some(child);
+ self
+ }
+
+ pub fn child(&self) -> Option<&CommandContextBuilder<S>> {
+ self.child.as_ref()
+ }
+
+ pub fn last_child(&self) -> Option<&CommandContextBuilder<S>> {
+ let mut result = self;
+ while let Some(child) = result.child() {
+ result = child;
+ }
+ Some(result)
+ }
+
+ pub fn command(&self) -> &dyn Command<S> {
+ &*self.command
+ }
+
+ pub fn nodes(&self) -> &Vec<ParsedCommandNode<S>> {
+ &self.nodes
+ }
+
+ pub fn build(self, input: &str) -> CommandContext<S> {
+ CommandContext {
+ source: self.source,
+ input,
+ arguments: self.arguments,
+ command: self.command,
+ root_node: self.root_node,
+ nodes: self.nodes,
+ range: self.range,
+ child: self.child.map(|child| child.build(input)),
+ modifier: self.modifier,
+ forks: self.forks,
+ }
+ }
+
+ pub fn dispatcher(&self) -> &CommandDispatcher<S> {
+ &self.dispatcher
+ }
+
+ pub fn range(&self) -> &StringRange {
+ &self.range
+ }
+
+ pub fn find_suggestion_context(&self, cursor: i32) -> Result<SuggestionContext<S>, String> {
+ if self.range.start() <= cursor {
+ if self.range.end() < cursor {
+ if let Some(child) = self.child() {
+ child.find_suggestion_context(cursor);
+ } else if !self.nodes.is_empty() {
+ let last = self.nodes.last().unwrap();
+ let end = last.range().end() + 1;
+ return SuggestionContext::new(last.node(), end);
+ } else {
+ return SuggestionContext::new(self.root_node, self.range.start());
+ }
+ } else {
+ let prev = self.root_node;
+ for node in &self.nodes {
+ let node_range = node.range();
+ if node_range.start() <= cursor && cursor <= node_range.end() {
+ return SuggestionContext::new(prev, node_range.start());
+ }
+ prev = node.node();
+ }
+ if prev.is_none() {
+ return Err(String::from("Can't find node before cursor"));
+ }
+ return SuggestionContext::new(prev.unwrap(), self.range.start());
+ }
+ }
+ Err(String::from("Can't find node before cursor"))
+ }
+}
diff --git a/azalea-brigadier/src/context/parsed_argument.rs b/azalea-brigadier/src/context/parsed_argument.rs
index e69de29b..5f9c2cdb 100644
--- a/azalea-brigadier/src/context/parsed_argument.rs
+++ b/azalea-brigadier/src/context/parsed_argument.rs
@@ -0,0 +1,24 @@
+use super::string_range::StringRange;
+
+#[derive(PartialEq, Eq, Hash)]
+pub struct ParsedArgument<S, T> {
+ range: StringRange,
+ result: T,
+}
+
+impl<S, T> ParsedArgument<S, T> {
+ fn new(start: usize, end: usize, result: T) -> Self {
+ Self {
+ range: StringRange::between(start, end),
+ result,
+ }
+ }
+
+ fn range(&self) -> &StringRange {
+ &self.range
+ }
+
+ fn result(&self) -> &T {
+ &self.result
+ }
+}
diff --git a/azalea-brigadier/src/context/parsed_command_node.rs b/azalea-brigadier/src/context/parsed_command_node.rs
index e69de29b..98e99959 100644
--- a/azalea-brigadier/src/context/parsed_command_node.rs
+++ b/azalea-brigadier/src/context/parsed_command_node.rs
@@ -0,0 +1,22 @@
+use super::string_range::StringRange;
+use crate::tree::command_node::CommandNode;
+
+#[derive(Hash, PartialEq, Eq, Debug, Clone)]
+pub struct ParsedCommandNode<S> {
+ node: dyn CommandNode<S>,
+ range: StringRange,
+}
+
+impl<S> ParsedCommandNode<S> {
+ fn new(node: dyn CommandNode<S>, range: StringRange) -> Self {
+ Self { node, range }
+ }
+
+ fn node(&self) -> &dyn CommandNode<S> {
+ &self.node
+ }
+
+ fn range(&self) -> &StringRange {
+ &self.range
+ }
+}
diff --git a/azalea-brigadier/src/context/string_range.rs b/azalea-brigadier/src/context/string_range.rs
index e69de29b..d775ab68 100644
--- a/azalea-brigadier/src/context/string_range.rs
+++ b/azalea-brigadier/src/context/string_range.rs
@@ -0,0 +1,45 @@
+use std::cmp;
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct StringRange {
+ start: usize,
+ end: usize,
+}
+
+impl StringRange {
+ pub fn new(start: usize, end: usize) -> Self {
+ Self { start, end }
+ }
+
+ pub fn at(pos: usize) -> Self {
+ Self::new(pos, pos)
+ }
+
+ pub fn between(start: usize, end: usize) -> Self {
+ Self::new(start, end)
+ }
+
+ pub fn encompassing(a: &Self, b: &Self) -> Self {
+ Self::new(cmp::min(a.start, b.start), cmp::max(a.end, b.end))
+ }
+
+ pub fn start(&self) -> usize {
+ self.start
+ }
+
+ pub fn end(&self) -> usize {
+ self.end
+ }
+
+ pub fn get(&self, reader: &str) -> &str {
+ &reader[self.start..self.end]
+ }
+
+ pub fn is_empty(&self) -> bool {
+ self.start == self.end
+ }
+
+ pub fn length(&self) -> usize {
+ self.end - self.start
+ }
+}
diff --git a/azalea-brigadier/src/context/suggestion_context.rs b/azalea-brigadier/src/context/suggestion_context.rs
index e69de29b..540a5f23 100644
--- a/azalea-brigadier/src/context/suggestion_context.rs
+++ b/azalea-brigadier/src/context/suggestion_context.rs
@@ -0,0 +1,6 @@
+use crate::tree::command_node::CommandNode;
+
+pub struct SuggestionContext<S> {
+ parent: dyn CommandNode<S>,
+ start_pos: usize,
+}