mirror of
https://github.com/mat-1/azalea.git
synced 2024-09-19 22:52:32 +00:00
stuff
This commit is contained in:
parent
eb111be1f1
commit
760816c81f
6 changed files with 164 additions and 30 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
use std::any::Any;
|
||||||
|
|
||||||
use super::bool_argument_type::BoolArgumentType;
|
use super::bool_argument_type::BoolArgumentType;
|
||||||
use crate::{
|
use crate::{
|
||||||
context::command_context::CommandContext,
|
context::command_context::CommandContext,
|
||||||
|
@ -31,8 +33,7 @@ impl Types for BrigadierTypes {
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#[clonable]
|
pub trait ArgumentType {
|
||||||
pub trait ArgumentType: Clone {
|
|
||||||
type Into;
|
type Into;
|
||||||
// T parse(StringReader reader) throws CommandSyntaxException;
|
// T parse(StringReader reader) throws CommandSyntaxException;
|
||||||
|
|
||||||
|
@ -49,7 +50,7 @@ pub trait ArgumentType: Clone {
|
||||||
fn list_suggestions<S>(
|
fn list_suggestions<S>(
|
||||||
&self,
|
&self,
|
||||||
context: &CommandContext<S>,
|
context: &CommandContext<S>,
|
||||||
builder: &mut SuggestionsBuilder,
|
builder: &SuggestionsBuilder,
|
||||||
) -> Result<Suggestions, CommandSyntaxException>
|
) -> Result<Suggestions, CommandSyntaxException>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
|
|
|
@ -3,7 +3,10 @@ use crate::{
|
||||||
command::Command,
|
command::Command,
|
||||||
redirect_modifier::RedirectModifier,
|
redirect_modifier::RedirectModifier,
|
||||||
single_redirect_modifier::SingleRedirectModifier,
|
single_redirect_modifier::SingleRedirectModifier,
|
||||||
tree::{command_node::CommandNode, root_command_node::RootCommandNode},
|
tree::{
|
||||||
|
command_node::{BaseCommandNode, CommandNode},
|
||||||
|
root_command_node::RootCommandNode,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct BaseArgumentBuilder<'a, S>
|
pub struct BaseArgumentBuilder<'a, S>
|
||||||
|
@ -11,10 +14,10 @@ where
|
||||||
S: Sized,
|
S: Sized,
|
||||||
{
|
{
|
||||||
arguments: RootCommandNode<'a, S>,
|
arguments: RootCommandNode<'a, S>,
|
||||||
command: Option<&'a dyn Command<S>>,
|
command: Option<Box<dyn Command<S>>>,
|
||||||
requirement: &'a dyn Fn(&S) -> bool,
|
requirement: Box<dyn Fn(&S) -> bool>,
|
||||||
target: Option<&'a dyn CommandNode<S>>,
|
target: Option<Box<dyn CommandNode<S>>>,
|
||||||
modifier: Option<&'a dyn RedirectModifier<S>>,
|
modifier: Option<Box<dyn RedirectModifier<S>>>,
|
||||||
forks: bool,
|
forks: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,15 +25,18 @@ pub trait ArgumentBuilder<S, T>
|
||||||
where
|
where
|
||||||
T: ArgumentBuilder<S, T>,
|
T: ArgumentBuilder<S, T>,
|
||||||
{
|
{
|
||||||
fn build(self) -> dyn CommandNode<S>;
|
fn build(self) -> Box<dyn CommandNode<S>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> BaseArgumentBuilder<'_, S> {
|
impl<'a, S> BaseArgumentBuilder<'a, S> {
|
||||||
pub fn then(&mut self, command: dyn CommandNode<S>) -> Result<&mut Self, String> {
|
pub fn then(
|
||||||
|
&mut self,
|
||||||
|
command: Box<dyn ArgumentBuilder<S, Self>>,
|
||||||
|
) -> Result<&mut Self, String> {
|
||||||
if self.target.is_some() {
|
if self.target.is_some() {
|
||||||
return Err("Cannot add children to a redirected node".to_string());
|
return Err("Cannot add children to a redirected node".to_string());
|
||||||
}
|
}
|
||||||
self.command = command;
|
self.command = Some(command);
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,4 +109,24 @@ impl<S> BaseArgumentBuilder<'_, S> {
|
||||||
pub fn is_fork(&self) -> bool {
|
pub fn is_fork(&self) -> bool {
|
||||||
self.forks
|
self.forks
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> BaseCommandNode<'a, S> {
|
||||||
|
let result: BaseCommandNode<'a, S> = BaseCommandNode {
|
||||||
|
command: self.command,
|
||||||
|
requirement: self.requirement,
|
||||||
|
redirect: self.target,
|
||||||
|
modifier: self.modifier,
|
||||||
|
forks: self.forks,
|
||||||
|
|
||||||
|
arguments: Default::default(),
|
||||||
|
children: Default::default(),
|
||||||
|
literals: Default::default(),
|
||||||
|
};
|
||||||
|
|
||||||
|
for argument in self.arguments() {
|
||||||
|
result.add_child(argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
result
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
arguments::argument_type::ArgumentType, tree::literal_command_node::LiteralCommandNode,
|
arguments::argument_type::ArgumentType,
|
||||||
|
tree::{command_node::CommandNode, literal_command_node::LiteralCommandNode},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::argument_builder::BaseArgumentBuilder;
|
use super::argument_builder::{ArgumentBuilder, BaseArgumentBuilder};
|
||||||
|
|
||||||
pub struct LiteralArgumentBuilder<'a, S> {
|
pub struct LiteralArgumentBuilder<'a, S> {
|
||||||
literal: String,
|
literal: String,
|
||||||
|
@ -21,9 +22,14 @@ impl<'a, S> LiteralArgumentBuilder<'a, S> {
|
||||||
pub fn literal(name: String) -> Self {
|
pub fn literal(name: String) -> Self {
|
||||||
Self::new(name)
|
Self::new(name)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn build(self) -> LiteralCommandNode<'a, S> {
|
impl<'a, S, T> ArgumentBuilder<S, T> for LiteralArgumentBuilder<'a, S>
|
||||||
let result = LiteralCommandNode::new(self.literal, self.base);
|
where
|
||||||
|
T: ArgumentBuilder<S, T>,
|
||||||
|
{
|
||||||
|
fn build(self) -> Box<dyn CommandNode<S>> {
|
||||||
|
let result = LiteralCommandNode::new(self.literal, self.base.build());
|
||||||
|
|
||||||
for argument in self.base.arguments {
|
for argument in self.base.arguments {
|
||||||
result.add_child(argument);
|
result.add_child(argument);
|
||||||
|
|
|
@ -19,10 +19,10 @@ pub struct RequiredArgumentBuilder<'a, S> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, S> RequiredArgumentBuilder<'a, S> {
|
impl<'a, S> RequiredArgumentBuilder<'a, S> {
|
||||||
pub fn new(name: String, type_: dyn ArgumentType<Into = dyn Any>) -> Self {
|
pub fn new(name: String, type_: Box<dyn ArgumentType<Into = dyn Any>>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
name,
|
name,
|
||||||
type_: &type_,
|
type_: type_,
|
||||||
suggestions_provider: None,
|
suggestions_provider: None,
|
||||||
base: BaseArgumentBuilder::new(name, type_),
|
base: BaseArgumentBuilder::new(name, type_),
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ where
|
||||||
fn list_suggestions(
|
fn list_suggestions(
|
||||||
&self,
|
&self,
|
||||||
context: CommandContext<S>,
|
context: CommandContext<S>,
|
||||||
builder: &mut SuggestionsBuilder,
|
builder: &SuggestionsBuilder,
|
||||||
) -> Result<Suggestions, CommandSyntaxException> {
|
) -> Result<Suggestions, CommandSyntaxException> {
|
||||||
if self.custom_suggestions.is_none() {
|
if self.custom_suggestions.is_none() {
|
||||||
self.get_type().list_suggestions(context, builder)
|
self.get_type().list_suggestions(context, builder)
|
||||||
|
@ -118,6 +118,10 @@ where
|
||||||
fn get_examples(&self) -> Vec<String> {
|
fn get_examples(&self) -> Vec<String> {
|
||||||
self.type_.get_examples()
|
self.type_.get_examples()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn base(&self) -> &BaseCommandNode<S> {
|
||||||
|
&self.base
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> Display for ArgumentCommandNode<'_, S> {
|
impl<S> Display for ArgumentCommandNode<'_, S> {
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
use super::{argument_command_node::ArgumentCommandNode, literal_command_node::LiteralCommandNode};
|
use super::{
|
||||||
|
argument_command_node::ArgumentCommandNode, literal_command_node::LiteralCommandNode,
|
||||||
|
root_command_node::RootCommandNode,
|
||||||
|
};
|
||||||
use crate::{
|
use crate::{
|
||||||
arguments::argument_type::ArgumentType,
|
arguments::argument_type::ArgumentType,
|
||||||
builder::argument_builder::ArgumentBuilder,
|
builder::argument_builder::ArgumentBuilder,
|
||||||
|
@ -12,19 +15,98 @@ use crate::{
|
||||||
use dyn_clonable::*;
|
use dyn_clonable::*;
|
||||||
use std::{any::Any, collections::HashMap, fmt::Debug};
|
use std::{any::Any, collections::HashMap, fmt::Debug};
|
||||||
|
|
||||||
#[derive(Default)]
|
|
||||||
pub struct BaseCommandNode<'a, S> {
|
pub struct BaseCommandNode<'a, S> {
|
||||||
children: HashMap<String, &'a dyn CommandNode<S>>,
|
children: HashMap<String, Box<dyn CommandNode<S>>>,
|
||||||
literals: HashMap<String, LiteralCommandNode<'a, S>>,
|
literals: HashMap<String, LiteralCommandNode<'a, S>>,
|
||||||
arguments: HashMap<String, ArgumentCommandNode<'a, S>>,
|
arguments: HashMap<String, ArgumentCommandNode<'a, S>>,
|
||||||
requirement: Option<&'a dyn Fn(&S) -> bool>,
|
requirement: Box<dyn Fn(&S) -> bool>,
|
||||||
redirect: Option<&'a dyn CommandNode<S>>,
|
redirect: Option<Box<dyn CommandNode<S>>>,
|
||||||
modifier: Option<&'a dyn RedirectModifier<S>>,
|
modifier: Option<Box<dyn RedirectModifier<S>>>,
|
||||||
forks: bool,
|
forks: bool,
|
||||||
command: Option<&'a dyn Command<S>>,
|
command: Option<Box<dyn Command<S>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<S> BaseCommandNode<'_, S> {}
|
impl<S> BaseCommandNode<'_, S> {
|
||||||
|
pub fn command(&self) -> &Option<Box<dyn Command<S>>> {
|
||||||
|
&self.command
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn children(&self) -> &HashMap<String, Box<dyn CommandNode<S>>> {
|
||||||
|
&self.children
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn child(&self, name: &str) -> Option<&dyn CommandNode<S>> {
|
||||||
|
self.children.get(name).map(|child| child.as_ref())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn redirect(&self) -> Option<&dyn CommandNode<S>> {
|
||||||
|
self.redirect.as_ref().map(|redirect| redirect.as_ref())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn redirect_modifier(&self) -> Option<&dyn RedirectModifier<S>> {
|
||||||
|
self.modifier.as_ref().map(|modifier| modifier.as_ref())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn can_use(&self, source: S) -> bool {
|
||||||
|
(self.requirement)(&source)
|
||||||
|
}
|
||||||
|
|
||||||
|
// public void addChild(final CommandNode<S> node) {
|
||||||
|
// if (node instanceof RootCommandNode) {
|
||||||
|
// throw new UnsupportedOperationException("Cannot add a RootCommandNode as a child to any other CommandNode");
|
||||||
|
// }
|
||||||
|
|
||||||
|
// final CommandNode<S> child = children.get(node.getName());
|
||||||
|
// if (child != null) {
|
||||||
|
// // We've found something to merge onto
|
||||||
|
// if (node.getCommand() != null) {
|
||||||
|
// child.command = node.getCommand();
|
||||||
|
// }
|
||||||
|
// for (final CommandNode<S> grandchild : node.getChildren()) {
|
||||||
|
// child.addChild(grandchild);
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// children.put(node.getName(), node);
|
||||||
|
// if (node instanceof LiteralCommandNode) {
|
||||||
|
// literals.put(node.getName(), (LiteralCommandNode<S>) node);
|
||||||
|
// } else if (node instanceof ArgumentCommandNode) {
|
||||||
|
// arguments.put(node.getName(), (ArgumentCommandNode<S, ?>) node);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
pub fn add_child(&self, node: &dyn CommandNode<S>) -> Result<(), String> {
|
||||||
|
if (&node as &dyn Any).is::<RootCommandNode<S>>() {
|
||||||
|
return Err(String::from(
|
||||||
|
"Cannot add a RootCommandNode as a child to any other CommandNode",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let child = self.children.get(node.name());
|
||||||
|
if let Some(child) = child {
|
||||||
|
// We've found something to merge onto
|
||||||
|
if let Some(command) = node.base.command() {
|
||||||
|
child.command = Some(command);
|
||||||
|
}
|
||||||
|
for grandchild in node.children() {
|
||||||
|
child.add_child(grandchild)?;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.children.insert(node.name().to_string(), node);
|
||||||
|
if let Some(literal) =
|
||||||
|
&node.clone_boxed() as &dyn Any as &dyn Any as &LiteralCommandNode<S>
|
||||||
|
{
|
||||||
|
self.literals
|
||||||
|
.insert(node.name().to_string(), literal.clone_boxed());
|
||||||
|
} else if let Some(argument) =
|
||||||
|
&node.clone_boxed() as &dyn Any as &dyn Any as &ArgumentCommandNode<S>
|
||||||
|
{
|
||||||
|
self.arguments
|
||||||
|
.insert(node.name().to_string(), argument.clone_boxed());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<S> Clone for BaseCommandNode<'_, S> {
|
impl<S> Clone for BaseCommandNode<'_, S> {
|
||||||
fn clone(&self) -> Self {
|
fn clone(&self) -> Self {
|
||||||
|
@ -56,8 +138,22 @@ impl<S> Debug for BaseCommandNode<'_, S> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[clonable]
|
impl<S> Default for BaseCommandNode<'_, S> {
|
||||||
pub trait CommandNode<S>: Clone {
|
fn default() -> Self {
|
||||||
|
Self {
|
||||||
|
children: HashMap::new(),
|
||||||
|
literals: HashMap::new(),
|
||||||
|
arguments: HashMap::new(),
|
||||||
|
requirement: Box::new(|_| true),
|
||||||
|
redirect: None,
|
||||||
|
modifier: None,
|
||||||
|
forks: false,
|
||||||
|
command: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait CommandNode<S> {
|
||||||
fn name(&self) -> &str;
|
fn name(&self) -> &str;
|
||||||
fn usage_text(&self) -> &str;
|
fn usage_text(&self) -> &str;
|
||||||
fn parse(
|
fn parse(
|
||||||
|
@ -68,9 +164,10 @@ pub trait CommandNode<S>: Clone {
|
||||||
fn list_suggestions(
|
fn list_suggestions(
|
||||||
&self,
|
&self,
|
||||||
context: CommandContext<S>,
|
context: CommandContext<S>,
|
||||||
builder: SuggestionsBuilder,
|
builder: &SuggestionsBuilder,
|
||||||
) -> Result<Suggestions, CommandSyntaxException>;
|
) -> Result<Suggestions, CommandSyntaxException>;
|
||||||
fn is_valid_input(&self, input: &str) -> bool;
|
fn is_valid_input(&self, input: &str) -> bool;
|
||||||
fn create_builder(&self) -> dyn ArgumentBuilder<S, dyn Any>;
|
fn create_builder(&self) -> dyn ArgumentBuilder<S, dyn Any>;
|
||||||
fn get_examples(&self) -> Vec<String>;
|
fn get_examples(&self) -> Vec<String>;
|
||||||
|
fn base(&self) -> &BaseCommandNode<S>;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue