mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 06:16:04 +00:00
a
This commit is contained in:
parent
270507736a
commit
eb111be1f1
33 changed files with 188 additions and 260 deletions
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -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>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -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()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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_,
|
||||||
|
|
|
@ -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>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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(),
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -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>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -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>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>,
|
||||||
|
|
|
@ -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_)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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>")
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
|
Loading…
Add table
Reference in a new issue