1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 14:26:04 +00:00
This commit is contained in:
Ubuntu 2022-01-13 00:43:09 +00:00
parent 270507736a
commit eb111be1f1
33 changed files with 188 additions and 260 deletions

View file

@ -0,0 +1 @@

View file

@ -7,19 +7,6 @@ use crate::{
}; };
use dyn_clonable::*; use dyn_clonable::*;
#[clonable]
// This should be applied to an Enum
pub trait Types: Clone {
fn bool(value: bool) -> Self
where
Self: Sized;
/// Get the less specific ArgumentType from this enum
fn inner<T>(&self) -> Box<dyn ArgumentType<T>>
where
Self: Sized;
}
/* /*
#[derive(Types)] #[derive(Types)]
enum BrigadierTypes { enum BrigadierTypes {
@ -45,10 +32,8 @@ impl Types for BrigadierTypes {
*/ */
#[clonable] #[clonable]
pub trait ArgumentType<T: ?Sized>: Clone pub trait ArgumentType: Clone {
where type Into;
T: Types,
{
// T parse(StringReader reader) throws CommandSyntaxException; // T parse(StringReader reader) throws CommandSyntaxException;
// default <S> CompletableFuture<Suggestions> listSuggestions(final CommandContext<S> context, final SuggestionsBuilder builder) { // default <S> CompletableFuture<Suggestions> listSuggestions(final CommandContext<S> context, final SuggestionsBuilder builder) {
@ -59,17 +44,16 @@ where
// return Collections.emptyList(); // return Collections.emptyList();
// } // }
fn parse(&self, reader: &mut StringReader) -> Result<Box<T>, CommandSyntaxException>; fn parse(&self, reader: &mut StringReader) -> Result<Self::Into, CommandSyntaxException>;
fn list_suggestions<S>( fn list_suggestions<S>(
&self, &self,
context: &CommandContext<S, T>, context: &CommandContext<S>,
builder: &mut SuggestionsBuilder, builder: &mut SuggestionsBuilder,
) -> Result<Suggestions, CommandSyntaxException> ) -> Result<Suggestions, CommandSyntaxException>
where where
Self: Sized, Self: Sized,
S: Sized, S: Sized;
T: Sized;
fn get_examples(&self) -> Vec<String>; fn get_examples(&self) -> Vec<String>;
} }

View file

@ -5,27 +5,25 @@ use crate::{
suggestion::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder}, suggestion::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder},
}; };
use super::argument_type::{ArgumentType, Types}; use super::argument_type::ArgumentType;
#[derive(Clone)] #[derive(Clone)]
pub struct BoolArgumentType {} pub struct BoolArgumentType {}
impl<T> ArgumentType<T> for BoolArgumentType impl ArgumentType for BoolArgumentType {
where type Into = bool;
T: Types,
{ fn parse(&self, reader: &mut StringReader) -> Result<Self::Into, CommandSyntaxException> {
fn parse(&self, reader: &mut StringReader) -> Result<T, CommandSyntaxException> { Ok(reader.read_boolean()?)
Ok(T::bool(reader.read_boolean()?))
} }
fn list_suggestions<S>( fn list_suggestions<S>(
&self, &self,
context: &CommandContext<S, T>, context: &CommandContext<S>,
builder: &mut SuggestionsBuilder, builder: &mut SuggestionsBuilder,
) -> Result<Suggestions, CommandSyntaxException> ) -> Result<Suggestions, CommandSyntaxException>
where where
S: Sized, S: Sized,
T: Sized,
{ {
// if ("true".startsWith(builder.getRemainingLowerCase())) { // if ("true".startsWith(builder.getRemainingLowerCase())) {
// builder.suggest("true"); // builder.suggest("true");
@ -55,7 +53,7 @@ impl BoolArgumentType {
Self {} Self {}
} }
fn get_bool<S, T>(context: CommandContext<S, T>, name: String) { fn get_bool<S>(context: CommandContext<S>, name: String) {
context.get_argument::<bool>(name) context.get_argument::<bool>(name)
} }
} }

View file

@ -1,33 +1,32 @@
use crate::{ use crate::{
arguments::argument_type::{ArgumentType, Types}, arguments::argument_type::ArgumentType,
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::CommandNode, root_command_node::RootCommandNode},
}; };
pub struct BaseArgumentBuilder<'a, S, T> pub struct BaseArgumentBuilder<'a, S>
where where
S: Sized, S: Sized,
T: Sized + ArgumentType<dyn Types>,
{ {
arguments: RootCommandNode<'a, S, T>, arguments: RootCommandNode<'a, S>,
command: Option<&'a dyn Command<S, T>>, command: Option<&'a dyn Command<S>>,
requirement: &'a dyn Fn(&S) -> bool, requirement: &'a dyn Fn(&S) -> bool,
target: Option<&'a dyn CommandNode<S, T>>, target: Option<&'a dyn CommandNode<S>>,
modifier: Option<&'a dyn RedirectModifier<S, T>>, modifier: Option<&'a dyn RedirectModifier<S>>,
forks: bool, forks: bool,
} }
pub trait ArgumentBuilder<S, T> { pub trait ArgumentBuilder<S, T>
fn build(self) -> dyn CommandNode<S, T>; where
T: ArgumentBuilder<S, T>,
{
fn build(self) -> dyn CommandNode<S>;
} }
impl<S, T> BaseArgumentBuilder<'_, S, T> impl<S> BaseArgumentBuilder<'_, S> {
where pub fn then(&mut self, command: dyn CommandNode<S>) -> Result<&mut Self, String> {
T: ArgumentType<dyn Types>,
{
pub fn then(&mut self, command: dyn CommandNode<S, T>) -> Result<&mut T, 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());
} }
@ -35,20 +34,20 @@ where
Ok(self) Ok(self)
} }
pub fn arguments(&self) -> &Vec<&dyn CommandNode<S, T>> { pub fn arguments(&self) -> &Vec<&dyn CommandNode<S>> {
&self.arguments.get_children() &self.arguments.get_children()
} }
pub fn executes(&mut self, command: dyn Command<S, T>) -> &mut T { pub fn executes(&mut self, command: dyn Command<S>) -> &mut Self {
self.command = command; self.command = command;
self self
} }
pub fn command(&self) -> dyn Command<S, T> { pub fn command(&self) -> dyn Command<S> {
self.command self.command
} }
pub fn requires(&mut self, requirement: &dyn Fn(&S) -> bool) -> &mut T { pub fn requires(&mut self, requirement: &dyn Fn(&S) -> bool) -> &mut Self {
self.requirement = requirement; self.requirement = requirement;
self self
} }
@ -57,33 +56,33 @@ where
self.requirement self.requirement
} }
pub fn redirect(&mut self, target: &dyn CommandNode<S, T>) -> &mut T { pub fn redirect(&mut self, target: &dyn CommandNode<S>) -> &mut Self {
self.forward(target, None, false) self.forward(target, None, false)
} }
pub fn redirect_modifier( pub fn redirect_modifier(
&mut self, &mut self,
target: &dyn CommandNode<S, T>, target: &dyn CommandNode<S>,
modifier: &dyn SingleRedirectModifier<S, T>, modifier: &dyn SingleRedirectModifier<S>,
) -> &mut T { ) -> &mut Self {
// forward(target, modifier == null ? null : o -> Collections.singleton(modifier.apply(o)), false); // forward(target, modifier == null ? null : o -> Collections.singleton(modifier.apply(o)), false);
self.forward(target, modifier.map(|m| |o| vec![m.apply(o)]), false) self.forward(target, modifier.map(|m| |o| vec![m.apply(o)]), false)
} }
pub fn fork( pub fn fork(
&mut self, &mut self,
target: &dyn CommandNode<S, T>, target: &dyn CommandNode<S>,
modifier: &dyn RedirectModifier<S, T>, modifier: &dyn RedirectModifier<S>,
) -> &mut T { ) -> &mut Self {
self.forward(target, Some(modifier), true) self.forward(target, Some(modifier), true)
} }
pub fn forward( pub fn forward(
&mut self, &mut self,
target: &dyn CommandNode<S, T>, target: &dyn CommandNode<S>,
modifier: Option<&dyn RedirectModifier<S, T>>, modifier: Option<&dyn RedirectModifier<S>>,
fork: bool, fork: bool,
) -> Result<&mut T, String> { ) -> Result<&mut Self, String> {
if !self.arguments.get_children().is_empty() { if !self.arguments.get_children().is_empty() {
return Err("Cannot forward a node with children".to_string()); return Err("Cannot forward a node with children".to_string());
} }
@ -93,11 +92,11 @@ where
Ok(self) Ok(self)
} }
pub fn get_redirect(&self) -> Option<&dyn CommandNode<S, T>> { pub fn get_redirect(&self) -> Option<&dyn CommandNode<S>> {
self.target.as_ref() self.target.as_ref()
} }
pub fn get_redirect_modifier(&self) -> Option<&dyn RedirectModifier<S, T>> { pub fn get_redirect_modifier(&self) -> Option<&dyn RedirectModifier<S>> {
self.modifier.as_ref() self.modifier.as_ref()
} }

View file

@ -1,23 +1,16 @@
use crate::{ use crate::{
arguments::argument_type::{ArgumentType, Types}, arguments::argument_type::ArgumentType, tree::literal_command_node::LiteralCommandNode,
tree::literal_command_node::LiteralCommandNode,
}; };
use super::argument_builder::BaseArgumentBuilder; use super::argument_builder::BaseArgumentBuilder;
pub struct LiteralArgumentBuilder<'a, S, T> pub struct LiteralArgumentBuilder<'a, S> {
where
T: ArgumentType<dyn Types>,
{
literal: String, literal: String,
pub base: BaseArgumentBuilder<'a, S, T>, pub base: BaseArgumentBuilder<'a, S>,
} }
impl<'a, S, T> LiteralArgumentBuilder<'a, S, T> impl<'a, S> LiteralArgumentBuilder<'a, S> {
where
T: ArgumentType<dyn Types>,
{
pub fn new(literal: String) -> Self { pub fn new(literal: String) -> Self {
Self { Self {
literal, literal,
@ -29,7 +22,7 @@ where
Self::new(name) Self::new(name)
} }
pub fn build(self) -> LiteralCommandNode<'a, S, T> { pub fn build(self) -> LiteralCommandNode<'a, S> {
let result = LiteralCommandNode::new(self.literal, self.base); let result = LiteralCommandNode::new(self.literal, self.base);
for argument in self.base.arguments { for argument in self.base.arguments {

View file

@ -1,30 +1,25 @@
use crate::{ use crate::{
arguments::argument_type::{ArgumentType, Types}, arguments::argument_type::ArgumentType,
suggestion::suggestion_provider::SuggestionProvider, suggestion::suggestion_provider::SuggestionProvider,
tree::{argument_command_node::ArgumentCommandNode, command_node::BaseCommandNode}, tree::{argument_command_node::ArgumentCommandNode, command_node::BaseCommandNode},
}; };
use std::any::Any;
use super::argument_builder::BaseArgumentBuilder; use super::argument_builder::BaseArgumentBuilder;
pub struct RequiredArgumentBuilder<'a, S, T> pub struct RequiredArgumentBuilder<'a, S> {
where
T: ArgumentType<dyn Types>,
{
// private final String name; // private final String name;
// private final ArgumentType<T> type; // private final ArgumentType<T> type;
// private SuggestionProvider<S> suggestionsProvider = null; // private SuggestionProvider<S> suggestionsProvider = null;
name: String, name: String,
type_: &'a T, type_: Box<dyn ArgumentType<Into = dyn Any>>,
suggestions_provider: Option<&'a dyn SuggestionProvider<S, T>>, suggestions_provider: Option<&'a dyn SuggestionProvider<S>>,
pub base: BaseArgumentBuilder<'a, S, T>, pub base: BaseArgumentBuilder<'a, S>,
} }
impl<'a, S, T> RequiredArgumentBuilder<'a, S, T> impl<'a, S> RequiredArgumentBuilder<'a, S> {
where pub fn new(name: String, type_: dyn ArgumentType<Into = dyn Any>) -> Self {
T: ArgumentType<dyn Types>,
{
pub fn new(name: String, type_: T) -> Self {
Self { Self {
name, name,
type_: &type_, type_: &type_,
@ -33,20 +28,20 @@ where
} }
} }
pub fn argument(name: String, type_: T) -> Self { pub fn argument(name: String, type_: dyn ArgumentType<Into = dyn Any>) -> Self {
Self::new(name, type_) Self::new(name, type_)
} }
pub fn suggests(mut self, provider: &dyn SuggestionProvider<S, T>) -> Self { pub fn suggests(mut self, provider: &dyn SuggestionProvider<S>) -> Self {
self.suggestions_provider = Some(provider); self.suggestions_provider = Some(provider);
self self
} }
pub fn suggestions_provider(&self) -> Option<&dyn SuggestionProvider<S, T>> { pub fn suggestions_provider(&self) -> Option<&dyn SuggestionProvider<S>> {
self.suggestions_provider.as_ref() self.suggestions_provider.as_ref()
} }
pub fn get_type(&self) -> &T { pub fn get_type(&self) -> &dyn ArgumentType<Into = dyn Any> {
self.type_ self.type_
} }
@ -54,14 +49,14 @@ where
self.name self.name
} }
// final ArgumentCommandNode<S, T> result = new ArgumentCommandNode<>(getName(), getType(), getCommand(), getRequirement(), getRedirect(), getRedirectModifier(), isFork(), getSuggestionsProvider()); // final ArgumentCommandNode<S> result = new ArgumentCommandNode<>(getName(), getType(), getCommand(), getRequirement(), getRedirect(), getRedirectModifier(), isFork(), getSuggestionsProvider());
// for (final CommandNode<S> argument : getArguments()) { // for (final CommandNode<S> argument : getArguments()) {
// result.addChild(argument); // result.addChild(argument);
// } // }
// return result; // return result;
pub fn build(self) -> ArgumentCommandNode<'a, S, T> { pub fn build(self) -> ArgumentCommandNode<'a, S> {
let result = ArgumentCommandNode { let result = ArgumentCommandNode {
name: self.name, name: self.name,
type_: &self.type_, type_: &self.type_,

View file

@ -7,6 +7,6 @@ use dyn_clonable::*;
pub const SINGLE_SUCCESS: i32 = 1; pub const SINGLE_SUCCESS: i32 = 1;
#[clonable] #[clonable]
pub trait Command<S, T>: Clone { pub trait Command<S>: Clone {
fn run(&self, context: &mut CommandContext<S, T>) -> Result<i32, CommandSyntaxException>; fn run(&self, context: &mut CommandContext<S>) -> Result<i32, CommandSyntaxException>;
} }

View file

@ -1,22 +1,13 @@
use crate::{ use crate::{arguments::argument_type::ArgumentType, tree::root_command_node::RootCommandNode};
arguments::argument_type::{ArgumentType, Types},
tree::root_command_node::RootCommandNode,
};
/// The core command dispatcher, for registering, parsing, and executing commands. /// The core command dispatcher, for registering, parsing, and executing commands.
/// The `S` generic is a custom "source" type, such as a user or originator of a command /// The `S` generic is a custom "source" type, such as a user or originator of a command
#[derive(Default, Clone)] #[derive(Default, Clone)]
pub struct CommandDispatcher<'a, S, T> pub struct CommandDispatcher<'a, S> {
where root: RootCommandNode<'a, S>,
T: ArgumentType<dyn Types>,
{
root: RootCommandNode<'a, S, T>,
} }
impl<S, T> CommandDispatcher<'_, S, T> impl<S> CommandDispatcher<'_, S> {
where
T: ArgumentType<dyn Types>,
{
/// The string required to separate individual arguments in an input string /// The string required to separate individual arguments in an input string
/// ///
/// See: [`ARGUMENT_SEPARATOR_CHAR`] /// See: [`ARGUMENT_SEPARATOR_CHAR`]
@ -48,7 +39,7 @@ where
/// * `root` - the existing [`RootCommandNode`] to use as the basis for this tree /// * `root` - the existing [`RootCommandNode`] to use as the basis for this tree
/// # Returns /// # Returns
/// A new [`CommandDispatcher`] with the specified root node. /// A new [`CommandDispatcher`] with the specified root node.
fn new(root: RootCommandNode<S, T>) -> Self { fn new(root: RootCommandNode<S>) -> Self {
Self { root } Self { root }
} }
} }

View file

@ -6,22 +6,22 @@ use crate::{
arguments::argument_type::ArgumentType, command::Command, redirect_modifier::RedirectModifier, arguments::argument_type::ArgumentType, command::Command, redirect_modifier::RedirectModifier,
tree::command_node::CommandNode, tree::command_node::CommandNode,
}; };
use std::collections::HashMap; use std::{any::Any, collections::HashMap};
pub struct CommandContext<'a, S, T> { pub struct CommandContext<'a, S> {
source: S, source: S,
input: String, input: String,
command: &'a dyn Command<S, T>, command: &'a dyn Command<S>,
arguments: HashMap<String, ParsedArgument<T>>, arguments: HashMap<String, ParsedArgument<Box<dyn Any>>>,
root_node: &'a dyn CommandNode<S, T>, root_node: &'a dyn CommandNode<S>,
nodes: Vec<ParsedCommandNode<S, T>>, nodes: Vec<ParsedCommandNode<S>>,
range: StringRange, range: StringRange,
child: Option<&'a CommandContext<'a, S, T>>, child: Option<&'a CommandContext<'a, S>>,
modifier: Option<&'a dyn RedirectModifier<S, T>>, modifier: Option<&'a dyn RedirectModifier<S>>,
forks: bool, forks: bool,
} }
impl<S, T> CommandContext<'_, S, T> impl<S> CommandContext<'_, S>
where where
S: PartialEq, S: PartialEq,
{ {
@ -43,11 +43,11 @@ where
} }
} }
fn child(&self) -> &Option<CommandContext<S, T>> { fn child(&self) -> &Option<CommandContext<S>> {
&self.child &self.child
} }
fn last_child(&self) -> &CommandContext<S, T> { fn last_child(&self) -> &CommandContext<S> {
let mut result = self; let mut result = self;
while result.child.is_some() { while result.child.is_some() {
result = result.child.as_ref().unwrap(); result = result.child.as_ref().unwrap();
@ -55,7 +55,7 @@ where
result result
} }
fn command(&self) -> &dyn Command<S, T> { fn command(&self) -> &dyn Command<S> {
&self.command &self.command
} }

View file

@ -1,10 +1,8 @@
use std::collections::HashMap; use std::{any::Any, collections::HashMap};
use crate::{ use crate::{
arguments::argument_type::{ArgumentType, Types}, arguments::argument_type::ArgumentType, command::Command,
command::Command, command_dispatcher::CommandDispatcher, redirect_modifier::RedirectModifier,
command_dispatcher::CommandDispatcher,
redirect_modifier::RedirectModifier,
tree::command_node::CommandNode, tree::command_node::CommandNode,
}; };
@ -27,19 +25,16 @@ use super::{
// private boolean forks; // private boolean forks;
#[derive(Clone)] #[derive(Clone)]
pub struct CommandContextBuilder<'a, S, T> pub struct CommandContextBuilder<'a, S> {
where arguments: HashMap<String, ParsedArgument<Box<dyn Any>>>,
T: ArgumentType<dyn Types>, root_node: &'a dyn CommandNode<S>,
{ nodes: Vec<ParsedCommandNode<S>>,
arguments: HashMap<String, ParsedArgument<T>>, dispatcher: CommandDispatcher<'a, S>,
root_node: &'a dyn CommandNode<S, T>,
nodes: Vec<ParsedCommandNode<S, T>>,
dispatcher: CommandDispatcher<'a, S, T>,
source: S, source: S,
command: Box<dyn Command<S, T>>, command: Box<dyn Command<S>>,
child: Option<CommandContextBuilder<'a, S, T>>, child: Option<CommandContextBuilder<'a, S>>,
range: StringRange, range: StringRange,
modifier: Option<Box<dyn RedirectModifier<S, T>>>, modifier: Option<Box<dyn RedirectModifier<S>>>,
forks: bool, forks: bool,
} }
@ -50,14 +45,11 @@ where
// this.range = StringRange.at(start); // this.range = StringRange.at(start);
// } // }
impl<S, T> CommandContextBuilder<'_, S, T> impl<S> CommandContextBuilder<'_, S> {
where
T: ArgumentType<dyn Types>,
{
pub fn new( pub fn new(
dispatcher: CommandDispatcher<S, T>, dispatcher: CommandDispatcher<S>,
source: S, source: S,
root_node: dyn CommandNode<S, T>, root_node: dyn CommandNode<S>,
start: usize, start: usize,
) -> Self { ) -> Self {
Self { Self {
@ -78,25 +70,25 @@ where
&self.source &self.source
} }
pub fn root_node(&self) -> &dyn CommandNode<S, T> { pub fn root_node(&self) -> &dyn CommandNode<S> {
&self.root_node &self.root_node
} }
pub fn with_argument(mut self, name: String, argument: ParsedArgument<T>) -> Self { pub fn with_argument(mut self, name: String, argument: ParsedArgument<Box<dyn Any>>) -> Self {
self.arguments.insert(name, argument); self.arguments.insert(name, argument);
self self
} }
pub fn arguments(&self) -> &HashMap<String, ParsedArgument<T>> { pub fn arguments(&self) -> &HashMap<String, ParsedArgument<Box<dyn Any>>> {
&self.arguments &self.arguments
} }
pub fn with_command(mut self, command: &dyn Command<S, T>) -> Self { pub fn with_command(mut self, command: &dyn Command<S>) -> Self {
self.command = command; self.command = command;
self self
} }
pub fn with_node(mut self, node: dyn CommandNode<S, T>, range: StringRange) -> Self { pub fn with_node(mut self, node: dyn CommandNode<S>, range: StringRange) -> Self {
self.nodes.push(ParsedCommandNode::new(node, range)); self.nodes.push(ParsedCommandNode::new(node, range));
self.range = StringRange::encompassing(&self.range, &range); self.range = StringRange::encompassing(&self.range, &range);
self.modifier = node.redirect_modifier(); self.modifier = node.redirect_modifier();
@ -104,16 +96,16 @@ where
self self
} }
pub fn with_child(mut self, child: CommandContextBuilder<S, T>) -> Self { pub fn with_child(mut self, child: CommandContextBuilder<S>) -> Self {
self.child = Some(child); self.child = Some(child);
self self
} }
pub fn child(&self) -> Option<&CommandContextBuilder<S, T>> { pub fn child(&self) -> Option<&CommandContextBuilder<S>> {
self.child.as_ref() self.child.as_ref()
} }
pub fn last_child(&self) -> Option<&CommandContextBuilder<S, T>> { pub fn last_child(&self) -> Option<&CommandContextBuilder<S>> {
let mut result = self; let mut result = self;
while let Some(child) = result.child() { while let Some(child) = result.child() {
result = child; result = child;
@ -121,15 +113,15 @@ where
Some(result) Some(result)
} }
pub fn command(&self) -> &dyn Command<S, T> { pub fn command(&self) -> &dyn Command<S> {
&*self.command &*self.command
} }
pub fn nodes(&self) -> &Vec<ParsedCommandNode<S, T>> { pub fn nodes(&self) -> &Vec<ParsedCommandNode<S>> {
&self.nodes &self.nodes
} }
pub fn build(self, input: &str) -> CommandContext<S, T> { pub fn build(self, input: &str) -> CommandContext<S> {
CommandContext { CommandContext {
source: self.source, source: self.source,
input, input,
@ -144,7 +136,7 @@ where
} }
} }
pub fn dispatcher(&self) -> &CommandDispatcher<S, T> { pub fn dispatcher(&self) -> &CommandDispatcher<S> {
&self.dispatcher &self.dispatcher
} }
@ -152,7 +144,7 @@ where
&self.range &self.range
} }
pub fn find_suggestion_context(&self, cursor: i32) -> Result<SuggestionContext<S, T>, String> { pub fn find_suggestion_context(&self, cursor: i32) -> Result<SuggestionContext<S>, String> {
if self.range.start() <= cursor { if self.range.start() <= cursor {
if self.range.end() < cursor { if self.range.end() < cursor {
if let Some(child) = self.child() { if let Some(child) = self.child() {

View file

@ -3,12 +3,11 @@ use super::string_range::StringRange;
#[derive(PartialEq, Eq, Hash, Clone)] #[derive(PartialEq, Eq, Hash, Clone)]
pub struct ParsedArgument<T> { pub struct ParsedArgument<T> {
range: StringRange, range: StringRange,
// T is an item in an enum
result: T, result: T,
} }
impl<T> ParsedArgument<T> { impl<T> ParsedArgument<T> {
fn new(start: usize, end: usize, result: T) -> Self { fn new(start: usize, end: usize, result: &T) -> Self {
Self { Self {
range: StringRange::between(start, end), range: StringRange::between(start, end),
result, result,

View file

@ -1,17 +1,17 @@
use super::string_range::StringRange; use super::string_range::StringRange;
use crate::tree::command_node::CommandNode; use crate::tree::command_node::CommandNode;
pub struct ParsedCommandNode<S, T> { pub struct ParsedCommandNode<S> {
node: Box<dyn CommandNode<S, T>>, node: Box<dyn CommandNode<S>>,
range: StringRange, range: StringRange,
} }
impl<S, T> ParsedCommandNode<S, T> { impl<S> ParsedCommandNode<S> {
fn new(node: dyn CommandNode<S, T>, range: StringRange) -> Self { fn new(node: dyn CommandNode<S>, range: StringRange) -> Self {
Self { node, range } Self { node, range }
} }
fn node(&self) -> &dyn CommandNode<S, T> { fn node(&self) -> &dyn CommandNode<S> {
&self.node &self.node
} }
@ -20,7 +20,7 @@ impl<S, T> ParsedCommandNode<S, T> {
} }
} }
impl<S, T> Clone for ParsedCommandNode<S, T> { impl<S> Clone for ParsedCommandNode<S> {
fn clone_from(&mut self, source: &Self) { fn clone_from(&mut self, source: &Self) {
Self { Self {
node: self.node.clone(), node: self.node.clone(),

View file

@ -1,6 +1,6 @@
use crate::tree::command_node::CommandNode; use crate::tree::command_node::CommandNode;
pub struct SuggestionContext<'a, S, T> { pub struct SuggestionContext<'a, S> {
parent: &'a dyn CommandNode<S, T>, parent: &'a dyn CommandNode<S>,
start_pos: usize, start_pos: usize,
} }

View file

@ -0,0 +1 @@

View file

@ -0,0 +1 @@

View file

@ -6,6 +6,6 @@ use crate::{
}; };
#[clonable] #[clonable]
pub trait RedirectModifier<S, T>: Clone { pub trait RedirectModifier<S>: Clone {
fn apply(&self, context: CommandContext<S, T>) -> Result<Vec<S>, CommandSyntaxException>; fn apply(&self, context: CommandContext<S>) -> Result<Vec<S>, CommandSyntaxException>;
} }

View file

@ -0,0 +1 @@

View file

@ -3,6 +3,6 @@ use crate::{
exceptions::command_syntax_exception::CommandSyntaxException, exceptions::command_syntax_exception::CommandSyntaxException,
}; };
pub trait SingleRedirectModifier<S, T> { pub trait SingleRedirectModifier<S> {
fn apply(&self, context: CommandContext<S, T>) -> Result<S, CommandSyntaxException>; fn apply(&self, context: CommandContext<S>) -> Result<S, CommandSyntaxException>;
} }

View file

@ -5,10 +5,10 @@ use crate::{
use super::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder}; use super::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder};
pub trait SuggestionProvider<S, T> { pub trait SuggestionProvider<S> {
fn suggestions( fn suggestions(
&self, &self,
context: &CommandContext<S, T>, context: &CommandContext<S>,
builder: &SuggestionsBuilder, builder: &SuggestionsBuilder,
) -> Result<Suggestions, CommandSyntaxException>; ) -> Result<Suggestions, CommandSyntaxException>;
} }

View file

@ -4,7 +4,7 @@ use crate::{context::string_range::StringRange, message::Message};
use super::suggestion::Suggestion; use super::suggestion::Suggestion;
#[derive(PartialEq, Eq, Hash, Default)] #[derive(PartialEq, Eq, Hash)]
pub struct Suggestions { pub struct Suggestions {
range: StringRange, range: StringRange,
suggestions: Vec<Suggestions>, suggestions: Vec<Suggestions>,

View file

@ -1,7 +1,10 @@
use std::fmt::{Display, Formatter}; use std::{
any::Any,
fmt::{Display, Formatter},
};
use crate::{ use crate::{
arguments::argument_type::{ArgumentType, Types}, arguments::argument_type::ArgumentType,
builder::required_argument_builder::RequiredArgumentBuilder, builder::required_argument_builder::RequiredArgumentBuilder,
context::{ context::{
command_context::CommandContext, command_context_builder::CommandContextBuilder, command_context::CommandContext, command_context_builder::CommandContextBuilder,
@ -22,35 +25,27 @@ const USAGE_ARGUMENT_OPEN: &str = "<";
const USAGE_ARGUMENT_CLOSE: &str = ">"; const USAGE_ARGUMENT_CLOSE: &str = ">";
#[derive(Clone)] #[derive(Clone)]
pub struct ArgumentCommandNode<'a, S, T> pub struct ArgumentCommandNode<'a, S> {
where
// each argument command node has its own different type
T: ArgumentType<dyn Types>,
{
name: String, name: String,
type_: &'a T, type_: Box<dyn ArgumentType<Into = dyn Any>>,
custom_suggestions: Option<&'a dyn SuggestionProvider<S, T>>, custom_suggestions: Option<&'a dyn SuggestionProvider<S>>,
// custom_suggestions: &'a dyn SuggestionProvider<S, T>, // custom_suggestions: &'a dyn SuggestionProvider<S>,
// Since Rust doesn't have extending, we put the struct this is extending as the "base" field // Since Rust doesn't have extending, we put the struct this is extending as the "base" field
pub base: BaseCommandNode<'a, S, T>, pub base: BaseCommandNode<'a, S>,
} }
impl<S, T> ArgumentCommandNode<'_, S, T> impl<S> ArgumentCommandNode<'_, S> {
where fn get_type(&self) -> &dyn ArgumentType<Into = dyn Any> {
T: ArgumentType<dyn Types>, self.type_
{
fn get_type(&self) -> &T {
&self.type_
} }
fn custom_suggestions(&self) -> Option<&dyn SuggestionProvider<S, T>> { fn custom_suggestions(&self) -> Option<&dyn SuggestionProvider<S>> {
self.custom_suggestions self.custom_suggestions
} }
} }
impl<'a, S, T> CommandNode<S, T> for ArgumentCommandNode<'a, S, T> impl<'a, S> CommandNode<S> for ArgumentCommandNode<'a, S>
where where
T: ArgumentType<dyn Types> + Clone,
S: Clone, S: Clone,
{ {
fn name(&self) -> &str { fn name(&self) -> &str {
@ -60,11 +55,11 @@ where
fn parse( fn parse(
&self, &self,
reader: &mut StringReader, reader: &mut StringReader,
context_builder: CommandContextBuilder<S, T>, context_builder: CommandContextBuilder<S>,
) -> Result<(), CommandSyntaxException> { ) -> Result<(), CommandSyntaxException> {
// final int start = reader.getCursor(); // final int start = reader.getCursor();
// final T result = type.parse(reader); // final T result = type.parse(reader);
// final ParsedArgument<S, T> parsed = new ParsedArgument<>(start, reader.getCursor(), result); // final ParsedArgument<S> parsed = new ParsedArgument<>(start, reader.getCursor(), result);
// contextBuilder.withArgument(name, parsed); // contextBuilder.withArgument(name, parsed);
// contextBuilder.withNode(this, parsed.getRange()); // contextBuilder.withNode(this, parsed.getRange());
@ -81,7 +76,7 @@ where
fn list_suggestions( fn list_suggestions(
&self, &self,
context: CommandContext<S, T>, context: CommandContext<S>,
builder: &mut SuggestionsBuilder, builder: &mut SuggestionsBuilder,
) -> Result<Suggestions, CommandSyntaxException> { ) -> Result<Suggestions, CommandSyntaxException> {
if self.custom_suggestions.is_none() { if self.custom_suggestions.is_none() {
@ -105,7 +100,7 @@ where
USAGE_ARGUMENT_OPEN + self.name + USAGE_ARGUMENT_CLOSE USAGE_ARGUMENT_OPEN + self.name + USAGE_ARGUMENT_CLOSE
} }
fn create_builder(&self) -> RequiredArgumentBuilder<S, T> { fn create_builder(&self) -> RequiredArgumentBuilder<S> {
let builder = RequiredArgumentBuilder::argument(&self.name, &self.type_); let builder = RequiredArgumentBuilder::argument(&self.name, &self.type_);
builder.requires(self.base.get_requirement()); builder.requires(self.base.get_requirement());
builder.forward( builder.forward(
@ -125,10 +120,7 @@ where
} }
} }
impl<S, T> Display for ArgumentCommandNode<'_, S, T> impl<S> Display for ArgumentCommandNode<'_, S> {
where
T: ArgumentType<dyn Types>,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "<argument {}: {}>", self.name, self.type_) write!(f, "<argument {}: {}>", self.name, self.type_)
} }

View file

@ -1,6 +1,6 @@
use super::{argument_command_node::ArgumentCommandNode, literal_command_node::LiteralCommandNode}; use super::{argument_command_node::ArgumentCommandNode, literal_command_node::LiteralCommandNode};
use crate::{ use crate::{
arguments::argument_type::{ArgumentType, Types}, arguments::argument_type::ArgumentType,
builder::argument_builder::ArgumentBuilder, builder::argument_builder::ArgumentBuilder,
command::Command, command::Command,
context::{command_context::CommandContext, command_context_builder::CommandContextBuilder}, context::{command_context::CommandContext, command_context_builder::CommandContextBuilder},
@ -10,29 +10,23 @@ use crate::{
suggestion::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder}, suggestion::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder},
}; };
use dyn_clonable::*; use dyn_clonable::*;
use std::{collections::HashMap, fmt::Debug}; use std::{any::Any, collections::HashMap, fmt::Debug};
#[derive(Default)] #[derive(Default)]
pub struct BaseCommandNode<'a, S, T> pub struct BaseCommandNode<'a, S> {
where children: HashMap<String, &'a dyn CommandNode<S>>,
T: ArgumentType<dyn Types>, literals: HashMap<String, LiteralCommandNode<'a, S>>,
{ arguments: HashMap<String, ArgumentCommandNode<'a, S>>,
children: HashMap<String, &'a dyn CommandNode<S, T>>,
literals: HashMap<String, LiteralCommandNode<'a, S, T>>,
arguments: HashMap<String, ArgumentCommandNode<'a, S, T>>,
requirement: Option<&'a dyn Fn(&S) -> bool>, requirement: Option<&'a dyn Fn(&S) -> bool>,
redirect: Option<&'a dyn CommandNode<S, T>>, redirect: Option<&'a dyn CommandNode<S>>,
modifier: Option<&'a dyn RedirectModifier<S, T>>, modifier: Option<&'a dyn RedirectModifier<S>>,
forks: bool, forks: bool,
command: Option<&'a dyn Command<S, T>>, command: Option<&'a dyn Command<S>>,
} }
impl<S, T> BaseCommandNode<'_, S, T> where T: ArgumentType<dyn Types> {} impl<S> BaseCommandNode<'_, S> {}
impl<S, T> Clone for BaseCommandNode<'_, S, T> impl<S> Clone for BaseCommandNode<'_, S> {
where
T: ArgumentType<dyn Types>,
{
fn clone(&self) -> Self { fn clone(&self) -> Self {
Self { Self {
children: self.children.clone(), children: self.children.clone(),
@ -47,10 +41,7 @@ where
} }
} }
impl<S, T> Debug for BaseCommandNode<'_, S, T> impl<S> Debug for BaseCommandNode<'_, S> {
where
T: ArgumentType<dyn Types>,
{
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("BaseCommandNode") f.debug_struct("BaseCommandNode")
.field("children", &self.children) .field("children", &self.children)
@ -66,23 +57,20 @@ where
} }
#[clonable] #[clonable]
pub trait CommandNode<S, T>: Clone pub trait CommandNode<S>: Clone {
where
T: ArgumentType<dyn Types>,
{
fn name(&self) -> &str; fn name(&self) -> &str;
fn usage_text(&self) -> &str; fn usage_text(&self) -> &str;
fn parse( fn parse(
&self, &self,
reader: &mut StringReader, reader: &mut StringReader,
context_builder: CommandContextBuilder<S, T>, context_builder: CommandContextBuilder<S>,
) -> Result<(), CommandSyntaxException>; ) -> Result<(), CommandSyntaxException>;
fn list_suggestions( fn list_suggestions(
&self, &self,
context: CommandContext<S, T>, 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, T>; fn create_builder(&self) -> dyn ArgumentBuilder<S, dyn Any>;
fn get_examples(&self) -> Vec<String>; fn get_examples(&self) -> Vec<String>;
} }

View file

@ -1,5 +1,5 @@
use crate::{ use crate::{
arguments::argument_type::{ArgumentType, Types}, arguments::argument_type::ArgumentType,
builder::literal_argument_builder::LiteralArgumentBuilder, builder::literal_argument_builder::LiteralArgumentBuilder,
command::Command, command::Command,
context::{command_context::CommandContext, command_context_builder::CommandContextBuilder}, context::{command_context::CommandContext, command_context_builder::CommandContextBuilder},
@ -14,22 +14,15 @@ use crate::{
use super::command_node::{BaseCommandNode, CommandNode}; use super::command_node::{BaseCommandNode, CommandNode};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct LiteralCommandNode<'a, S, T> pub struct LiteralCommandNode<'a, S> {
where
// each argument command node has its own different type
T: ArgumentType<dyn Types>,
{
literal: String, literal: String,
literal_lowercase: String, literal_lowercase: String,
// Since Rust doesn't have extending, we put the struct this is extending as the "base" field // Since Rust doesn't have extending, we put the struct this is extending as the "base" field
pub base: BaseCommandNode<'a, S, T>, pub base: BaseCommandNode<'a, S>,
} }
impl<'a, S, T> LiteralCommandNode<'a, S, T> impl<'a, S> LiteralCommandNode<'a, S> {
where pub fn new(literal: String, base: BaseCommandNode<S>) -> Self {
T: ArgumentType<dyn Types>,
{
pub fn new(literal: String, base: BaseCommandNode<S, T>) -> Self {
let literal_lowercase = literal.to_lowercase(); let literal_lowercase = literal.to_lowercase();
Self { Self {
literal, literal,
@ -59,9 +52,8 @@ where
} }
} }
impl<S, T> CommandNode<S, T> for LiteralCommandNode<'_, S, T> impl<S> CommandNode<S> for LiteralCommandNode<'_, S>
where where
T: ArgumentType<dyn Types> + Clone,
S: Clone, S: Clone,
{ {
fn name(&self) -> &str { fn name(&self) -> &str {
@ -71,7 +63,7 @@ where
fn parse( fn parse(
&self, &self,
reader: StringReader, reader: StringReader,
context_builder: CommandContextBuilder<S, T>, context_builder: CommandContextBuilder<S>,
) -> Result<(), CommandSyntaxException> { ) -> Result<(), CommandSyntaxException> {
let start = reader.get_cursor(); let start = reader.get_cursor();
let end = self.parse(reader); let end = self.parse(reader);
@ -87,7 +79,7 @@ where
fn list_suggestions( fn list_suggestions(
&self, &self,
context: CommandContext<S, T>, context: CommandContext<S>,
builder: SuggestionsBuilder, builder: SuggestionsBuilder,
) -> Result<Suggestions, CommandSyntaxException> { ) -> Result<Suggestions, CommandSyntaxException> {
if self if self
@ -108,7 +100,7 @@ where
self.literal self.literal
} }
fn create_builder(&self) -> LiteralArgumentBuilder<S, T> { fn create_builder(&self) -> LiteralArgumentBuilder<S> {
let builder = LiteralArgumentBuilder::literal(self.literal()); let builder = LiteralArgumentBuilder::literal(self.literal());
builder.requires(self.requirement()); builder.requires(self.requirement());
builder.forward(self.redirect(), self.redirect_modifier(), self.is_fork()); builder.forward(self.redirect(), self.redirect_modifier(), self.is_fork());

View file

@ -1,7 +1,7 @@
use std::fmt::{Display, Formatter}; use std::fmt::{Display, Formatter};
use crate::{ use crate::{
arguments::argument_type::{ArgumentType, Types}, arguments::argument_type::ArgumentType,
context::{command_context::CommandContext, command_context_builder::CommandContextBuilder}, context::{command_context::CommandContext, command_context_builder::CommandContextBuilder},
exceptions::{ exceptions::{
builtin_exceptions::BuiltInExceptions, command_syntax_exception::CommandSyntaxException, builtin_exceptions::BuiltInExceptions, command_syntax_exception::CommandSyntaxException,
@ -13,18 +13,13 @@ use crate::{
use super::command_node::{BaseCommandNode, CommandNode}; use super::command_node::{BaseCommandNode, CommandNode};
#[derive(Clone, Default)] #[derive(Clone, Default)]
pub struct RootCommandNode<'a, S, T> pub struct RootCommandNode<'a, S> {
where
// each argument command node has its own different type
T: ArgumentType<dyn Types>,
{
// Since Rust doesn't have extending, we put the struct this is extending as the "base" field // Since Rust doesn't have extending, we put the struct this is extending as the "base" field
pub base: BaseCommandNode<'a, S, T>, pub base: BaseCommandNode<'a, S>,
} }
impl<S, T> CommandNode<S, T> for RootCommandNode<'_, S, T> impl<S> CommandNode<S> for RootCommandNode<'_, S>
where where
T: ArgumentType<dyn Types> + Clone,
S: Clone, S: Clone,
{ {
fn name(&self) -> &str { fn name(&self) -> &str {
@ -34,13 +29,13 @@ where
fn parse( fn parse(
&self, &self,
reader: StringReader, reader: StringReader,
context_builder: CommandContextBuilder<S, T>, context_builder: CommandContextBuilder<S>,
) -> Result<(), CommandSyntaxException> { ) -> Result<(), CommandSyntaxException> {
} }
fn list_suggestions( fn list_suggestions(
&self, &self,
context: CommandContext<S, T>, context: CommandContext<S>,
builder: SuggestionsBuilder, builder: SuggestionsBuilder,
) -> Result<Suggestions, CommandSyntaxException> { ) -> Result<Suggestions, CommandSyntaxException> {
Suggestions::empty() Suggestions::empty()
@ -63,10 +58,7 @@ where
} }
} }
impl<S, T> Display for RootCommandNode<'_, S, T> impl<S> Display for RootCommandNode<'_, S> {
where
T: ArgumentType<dyn Types>,
{
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "<root>") write!(f, "<root>")
} }