From 315f2258190b33c63df7797a97178019f5aea02b Mon Sep 17 00:00:00 2001 From: mat Date: Sun, 9 Jan 2022 22:33:45 -0600 Subject: add some more stuff from brigadier --- .../src/context/command_context_builder.rs | 180 +++++++++++++++++++++ 1 file changed, 180 insertions(+) (limited to 'azalea-brigadier/src/context/command_context_builder.rs') 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 { +// private final Map> arguments = new LinkedHashMap<>(); +// private final CommandNode rootNode; +// private final List> nodes = new ArrayList<>(); +// private final CommandDispatcher dispatcher; +// private S source; +// private Command command; +// private CommandContextBuilder child; +// private StringRange range; +// private RedirectModifier modifier = null; +// private boolean forks; + +#[derive(Clone)] +pub struct CommandContextBuilder { + arguments: HashMap>, + root_node: dyn CommandNode, + nodes: Vec>, + dispatcher: CommandDispatcher, + source: S, + command: Box>, + child: Option>, + range: StringRange, + modifier: Option>>, + forks: bool, +} + +// public CommandContextBuilder(final CommandDispatcher dispatcher, final S source, final CommandNode rootNode, final int start) { +// this.rootNode = rootNode; +// this.dispatcher = dispatcher; +// this.source = source; +// this.range = StringRange.at(start); +// } + +impl CommandContextBuilder { + pub fn new( + dispatcher: CommandDispatcher, + source: S, + root_node: dyn CommandNode, + 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 { + &self.root_node + } + + pub fn with_argument( + mut self, + name: String, + argument: ParsedArgument, + ) -> Self { + self.arguments.insert(name, argument); + self + } + + pub fn arguments(&self) -> &HashMap> { + &self.arguments + } + + pub fn with_command(mut self, command: Box>) -> Self { + self.command = command; + self + } + + pub fn with_node(mut self, node: dyn CommandNode, 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) -> Self { + self.child = Some(child); + self + } + + pub fn child(&self) -> Option<&CommandContextBuilder> { + self.child.as_ref() + } + + pub fn last_child(&self) -> Option<&CommandContextBuilder> { + let mut result = self; + while let Some(child) = result.child() { + result = child; + } + Some(result) + } + + pub fn command(&self) -> &dyn Command { + &*self.command + } + + pub fn nodes(&self) -> &Vec> { + &self.nodes + } + + pub fn build(self, input: &str) -> CommandContext { + 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 { + &self.dispatcher + } + + pub fn range(&self) -> &StringRange { + &self.range + } + + pub fn find_suggestion_context(&self, cursor: i32) -> Result, 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")) + } +} -- cgit v1.2.3