mirror of
https://github.com/mat-1/azalea.git
synced 2024-09-19 14:42: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 crate::{
|
||||
context::command_context::CommandContext,
|
||||
|
@ -31,8 +33,7 @@ impl Types for BrigadierTypes {
|
|||
}
|
||||
*/
|
||||
|
||||
#[clonable]
|
||||
pub trait ArgumentType: Clone {
|
||||
pub trait ArgumentType {
|
||||
type Into;
|
||||
// T parse(StringReader reader) throws CommandSyntaxException;
|
||||
|
||||
|
@ -49,7 +50,7 @@ pub trait ArgumentType: Clone {
|
|||
fn list_suggestions<S>(
|
||||
&self,
|
||||
context: &CommandContext<S>,
|
||||
builder: &mut SuggestionsBuilder,
|
||||
builder: &SuggestionsBuilder,
|
||||
) -> Result<Suggestions, CommandSyntaxException>
|
||||
where
|
||||
Self: Sized,
|
||||
|
|
|
@ -3,7 +3,10 @@ use crate::{
|
|||
command::Command,
|
||||
redirect_modifier::RedirectModifier,
|
||||
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>
|
||||
|
@ -11,10 +14,10 @@ where
|
|||
S: Sized,
|
||||
{
|
||||
arguments: RootCommandNode<'a, S>,
|
||||
command: Option<&'a dyn Command<S>>,
|
||||
requirement: &'a dyn Fn(&S) -> bool,
|
||||
target: Option<&'a dyn CommandNode<S>>,
|
||||
modifier: Option<&'a dyn RedirectModifier<S>>,
|
||||
command: Option<Box<dyn Command<S>>>,
|
||||
requirement: Box<dyn Fn(&S) -> bool>,
|
||||
target: Option<Box<dyn CommandNode<S>>>,
|
||||
modifier: Option<Box<dyn RedirectModifier<S>>>,
|
||||
forks: bool,
|
||||
}
|
||||
|
||||
|
@ -22,15 +25,18 @@ pub trait ArgumentBuilder<S, T>
|
|||
where
|
||||
T: ArgumentBuilder<S, T>,
|
||||
{
|
||||
fn build(self) -> dyn CommandNode<S>;
|
||||
fn build(self) -> Box<dyn CommandNode<S>>;
|
||||
}
|
||||
|
||||
impl<S> BaseArgumentBuilder<'_, S> {
|
||||
pub fn then(&mut self, command: dyn CommandNode<S>) -> Result<&mut Self, String> {
|
||||
impl<'a, S> BaseArgumentBuilder<'a, S> {
|
||||
pub fn then(
|
||||
&mut self,
|
||||
command: Box<dyn ArgumentBuilder<S, Self>>,
|
||||
) -> Result<&mut Self, String> {
|
||||
if self.target.is_some() {
|
||||
return Err("Cannot add children to a redirected node".to_string());
|
||||
}
|
||||
self.command = command;
|
||||
self.command = Some(command);
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
|
@ -103,4 +109,24 @@ impl<S> BaseArgumentBuilder<'_, S> {
|
|||
pub fn is_fork(&self) -> bool {
|
||||
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::{
|
||||
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> {
|
||||
literal: String,
|
||||
|
@ -21,9 +22,14 @@ impl<'a, S> LiteralArgumentBuilder<'a, S> {
|
|||
pub fn literal(name: String) -> Self {
|
||||
Self::new(name)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build(self) -> LiteralCommandNode<'a, S> {
|
||||
let result = LiteralCommandNode::new(self.literal, self.base);
|
||||
impl<'a, S, T> ArgumentBuilder<S, T> for LiteralArgumentBuilder<'a, S>
|
||||
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 {
|
||||
result.add_child(argument);
|
||||
|
|
|
@ -19,10 +19,10 @@ pub struct 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 {
|
||||
name,
|
||||
type_: &type_,
|
||||
type_: type_,
|
||||
suggestions_provider: None,
|
||||
base: BaseArgumentBuilder::new(name, type_),
|
||||
}
|
||||
|
|
|
@ -77,7 +77,7 @@ where
|
|||
fn list_suggestions(
|
||||
&self,
|
||||
context: CommandContext<S>,
|
||||
builder: &mut SuggestionsBuilder,
|
||||
builder: &SuggestionsBuilder,
|
||||
) -> Result<Suggestions, CommandSyntaxException> {
|
||||
if self.custom_suggestions.is_none() {
|
||||
self.get_type().list_suggestions(context, builder)
|
||||
|
@ -118,6 +118,10 @@ where
|
|||
fn get_examples(&self) -> Vec<String> {
|
||||
self.type_.get_examples()
|
||||
}
|
||||
|
||||
fn base(&self) -> &BaseCommandNode<S> {
|
||||
&self.base
|
||||
}
|
||||
}
|
||||
|
||||
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::{
|
||||
arguments::argument_type::ArgumentType,
|
||||
builder::argument_builder::ArgumentBuilder,
|
||||
|
@ -12,19 +15,98 @@ use crate::{
|
|||
use dyn_clonable::*;
|
||||
use std::{any::Any, collections::HashMap, fmt::Debug};
|
||||
|
||||
#[derive(Default)]
|
||||
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>>,
|
||||
arguments: HashMap<String, ArgumentCommandNode<'a, S>>,
|
||||
requirement: Option<&'a dyn Fn(&S) -> bool>,
|
||||
redirect: Option<&'a dyn CommandNode<S>>,
|
||||
modifier: Option<&'a dyn RedirectModifier<S>>,
|
||||
requirement: Box<dyn Fn(&S) -> bool>,
|
||||
redirect: Option<Box<dyn CommandNode<S>>>,
|
||||
modifier: Option<Box<dyn RedirectModifier<S>>>,
|
||||
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> {
|
||||
fn clone(&self) -> Self {
|
||||
|
@ -56,8 +138,22 @@ impl<S> Debug for BaseCommandNode<'_, S> {
|
|||
}
|
||||
}
|
||||
|
||||
#[clonable]
|
||||
pub trait CommandNode<S>: Clone {
|
||||
impl<S> Default for BaseCommandNode<'_, S> {
|
||||
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 usage_text(&self) -> &str;
|
||||
fn parse(
|
||||
|
@ -68,9 +164,10 @@ pub trait CommandNode<S>: Clone {
|
|||
fn list_suggestions(
|
||||
&self,
|
||||
context: CommandContext<S>,
|
||||
builder: SuggestionsBuilder,
|
||||
builder: &SuggestionsBuilder,
|
||||
) -> Result<Suggestions, CommandSyntaxException>;
|
||||
fn is_valid_input(&self, input: &str) -> bool;
|
||||
fn create_builder(&self) -> dyn ArgumentBuilder<S, dyn Any>;
|
||||
fn get_examples(&self) -> Vec<String>;
|
||||
fn base(&self) -> &BaseCommandNode<S>;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue