mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 14:26:04 +00:00
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
This commit is contained in:
parent
315f225819
commit
fec7a2bfed
10 changed files with 160 additions and 31 deletions
|
@ -5,7 +5,12 @@ use crate::{
|
|||
suggestion::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder},
|
||||
};
|
||||
|
||||
pub trait ArgumentType {
|
||||
pub trait ArgumentResult {}
|
||||
|
||||
pub trait ArgumentType<T>
|
||||
where
|
||||
T: ArgumentResult,
|
||||
{
|
||||
// T parse(StringReader reader) throws CommandSyntaxException;
|
||||
|
||||
// default <S> CompletableFuture<Suggestions> listSuggestions(final CommandContext<S> context, final SuggestionsBuilder builder) {
|
||||
|
@ -16,12 +21,13 @@ pub trait ArgumentType {
|
|||
// return Collections.emptyList();
|
||||
// }
|
||||
|
||||
fn parse<T>(reader: &mut StringReader) -> Result<T, CommandSyntaxException>;
|
||||
fn parse(&self, reader: &mut StringReader) -> Result<T, CommandSyntaxException>;
|
||||
|
||||
fn list_suggestions<S>(
|
||||
&self,
|
||||
context: &CommandContext<S>,
|
||||
builder: &mut SuggestionsBuilder,
|
||||
) -> Result<Suggestions, CommandSyntaxException>;
|
||||
|
||||
fn get_examples() -> Vec<String>;
|
||||
fn get_examples(&self) -> Vec<String>;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ use super::argument_type::ArgumentType;
|
|||
|
||||
struct BoolArgumentType {}
|
||||
|
||||
impl ArgumentType for BoolArgumentType {}
|
||||
impl ArgumentType<bool> for BoolArgumentType {}
|
||||
|
||||
impl BoolArgumentType {
|
||||
const EXAMPLES: &'static [&'static str] = &["true", "false"];
|
||||
|
|
|
@ -10,7 +10,7 @@ where
|
|||
T: ArgumentBuilder<S, T>,
|
||||
{
|
||||
arguments: RootCommandNode<S>,
|
||||
command: dyn Command<S>,
|
||||
command: Option<dyn Command<S>>,
|
||||
requirement: dyn Fn(&S) -> bool,
|
||||
target: Option<dyn CommandNode<S>>,
|
||||
modifier: Option<dyn RedirectModifier<S>>,
|
||||
|
@ -18,7 +18,6 @@ where
|
|||
}
|
||||
|
||||
pub trait ArgumentBuilder<S, T> {
|
||||
fn this() -> T;
|
||||
fn build(self) -> dyn CommandNode<S>;
|
||||
}
|
||||
|
||||
|
@ -92,11 +91,11 @@ where
|
|||
Ok(self)
|
||||
}
|
||||
|
||||
pub fn redirect(&self) -> Option<&dyn CommandNode<S>> {
|
||||
pub fn get_redirect(&self) -> Option<&dyn CommandNode<S>> {
|
||||
self.target.as_ref()
|
||||
}
|
||||
|
||||
pub fn redirect_modifier(&self) -> Option<&dyn RedirectModifier<S>> {
|
||||
pub fn get_redirect_modifier(&self) -> Option<&dyn RedirectModifier<S>> {
|
||||
self.modifier.as_ref()
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
use crate::{
|
||||
arguments::argument_type::ArgumentType,
|
||||
suggestion::suggestion_provider::SuggestionProvider,
|
||||
tree::{argument_command_node::ArgumentCommandNode, command_node::BaseCommandNode},
|
||||
};
|
||||
|
||||
use super::argument_builder::BaseArgumentBuilder;
|
||||
|
||||
// private RequiredArgumentBuilder(final String name, final ArgumentType<T> type) {
|
||||
// this.name = name;
|
||||
// this.type = type;
|
||||
// }
|
||||
|
||||
// public static <S, T> RequiredArgumentBuilder<S, T> argument(final String name, final ArgumentType<T> type) {
|
||||
// return new RequiredArgumentBuilder<>(name, type);
|
||||
// }
|
||||
|
||||
// public RequiredArgumentBuilder<S, T> suggests(final SuggestionProvider<S> provider) {
|
||||
// this.suggestionsProvider = provider;
|
||||
// return getThis();
|
||||
// }
|
||||
|
||||
// public SuggestionProvider<S> getSuggestionsProvider() {
|
||||
// return suggestionsProvider;
|
||||
// }
|
||||
|
||||
// @Override
|
||||
// protected RequiredArgumentBuilder<S, T> getThis() {
|
||||
// return this;
|
||||
// }
|
||||
|
||||
// public ArgumentType<T> getType() {
|
||||
// return type;
|
||||
// }
|
||||
|
||||
// public String getName() {
|
||||
// return name;
|
||||
// }
|
||||
|
||||
// public ArgumentCommandNode<S, T> build() {
|
||||
// final ArgumentCommandNode<S, T> result = new ArgumentCommandNode<>(getName(), getType(), getCommand(), getRequirement(), getRedirect(), getRedirectModifier(), isFork(), getSuggestionsProvider());
|
||||
|
||||
// for (final CommandNode<S> argument : getArguments()) {
|
||||
// result.addChild(argument);
|
||||
// }
|
||||
|
||||
// return result;
|
||||
// }
|
||||
|
||||
pub struct RequiredArgumentBuilder<S, T> {
|
||||
// private final String name;
|
||||
// private final ArgumentType<T> type;
|
||||
// private SuggestionProvider<S> suggestionsProvider = null;
|
||||
name: String,
|
||||
type_: dyn ArgumentType<T>,
|
||||
suggestions_provider: Option<dyn SuggestionProvider<S>>,
|
||||
|
||||
pub base: BaseArgumentBuilder<S, T>,
|
||||
}
|
||||
|
||||
impl<S, T> RequiredArgumentBuilder<S, T> {
|
||||
pub fn new(name: String, type_: dyn ArgumentType<T>) -> Self {
|
||||
Self {
|
||||
name,
|
||||
type_,
|
||||
suggestions_provider: None,
|
||||
base: BaseArgumentBuilder::new(name, type_),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn argument(name: String, type_: dyn ArgumentType<T>) -> Self {
|
||||
Self::new(name, type_)
|
||||
}
|
||||
|
||||
pub fn suggests(mut self, provider: dyn SuggestionProvider<S>) -> Self {
|
||||
self.suggestions_provider = Some(provider);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn suggestions_provider(&self) -> Option<&dyn SuggestionProvider<S>> {
|
||||
self.suggestions_provider.as_ref()
|
||||
}
|
||||
|
||||
pub fn get_type(&self) -> &dyn ArgumentType<T> {
|
||||
&self.type_
|
||||
}
|
||||
|
||||
pub fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
||||
// final ArgumentCommandNode<S, T> result = new ArgumentCommandNode<>(getName(), getType(), getCommand(), getRequirement(), getRedirect(), getRedirectModifier(), isFork(), getSuggestionsProvider());
|
||||
|
||||
// for (final CommandNode<S> argument : getArguments()) {
|
||||
// result.addChild(argument);
|
||||
// }
|
||||
|
||||
// return result;
|
||||
pub fn build(self) -> ArgumentCommandNode<S, T> {
|
||||
let result = ArgumentCommandNode {
|
||||
name: self.name,
|
||||
type_: &self.type_,
|
||||
base: BaseCommandNode {
|
||||
command: self.base.command,
|
||||
requirement: self.base.requirement,
|
||||
redirect: self.base.redirect,
|
||||
modifier: self.base.modifier,
|
||||
forks: self.base.forks,
|
||||
..BaseCommandNode::default()
|
||||
},
|
||||
custom_suggestions: self.base.custom_suggestions,
|
||||
};
|
||||
|
||||
for argument in self.base.arguments {
|
||||
result.add_child(argument);
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
}
|
|
@ -1,3 +1,5 @@
|
|||
use crate::tree::root_command_node::RootCommandNode;
|
||||
|
||||
/// 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
|
||||
pub struct CommandDispatcher<S> {
|
||||
|
|
|
@ -3,7 +3,9 @@ use super::{
|
|||
string_range::StringRange,
|
||||
};
|
||||
use crate::{
|
||||
arguments::argument_type::ArgumentType, command::Command, redirect_modifier::RedirectModifier,
|
||||
arguments::argument_type::{ArgumentResult, ArgumentType},
|
||||
command::Command,
|
||||
redirect_modifier::RedirectModifier,
|
||||
tree::command_node::CommandNode,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
@ -12,7 +14,7 @@ pub struct CommandContext<S> {
|
|||
source: S,
|
||||
input: String,
|
||||
command: dyn Command<S>,
|
||||
arguments: HashMap<String, ParsedArgument<S, dyn ArgumentType>>,
|
||||
arguments: HashMap<String, ParsedArgument<dyn ArgumentType<dyn ArgumentResult>>>,
|
||||
root_node: dyn CommandNode<S>,
|
||||
nodes: Vec<ParsedCommandNode<S>>,
|
||||
range: StringRange,
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
arguments::argument_type::ArgumentType, command::Command,
|
||||
command_dispatcher::CommandDispatcher, redirect_modifier::RedirectModifier,
|
||||
arguments::argument_type::{ArgumentResult, ArgumentType},
|
||||
command::Command,
|
||||
command_dispatcher::CommandDispatcher,
|
||||
redirect_modifier::RedirectModifier,
|
||||
tree::command_node::CommandNode,
|
||||
};
|
||||
|
||||
|
@ -26,7 +28,7 @@ use super::{
|
|||
|
||||
#[derive(Clone)]
|
||||
pub struct CommandContextBuilder<S> {
|
||||
arguments: HashMap<String, ParsedArgument<S, dyn ArgumentType>>,
|
||||
arguments: HashMap<String, ParsedArgument<dyn ArgumentType<dyn ArgumentResult>>>,
|
||||
root_node: dyn CommandNode<S>,
|
||||
nodes: Vec<ParsedCommandNode<S>>,
|
||||
dispatcher: CommandDispatcher<S>,
|
||||
|
@ -77,13 +79,15 @@ impl<S> CommandContextBuilder<S> {
|
|||
pub fn with_argument(
|
||||
mut self,
|
||||
name: String,
|
||||
argument: ParsedArgument<S, dyn ArgumentType>,
|
||||
argument: ParsedArgument<dyn ArgumentType<dyn ArgumentResult>>,
|
||||
) -> Self {
|
||||
self.arguments.insert(name, argument);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn arguments(&self) -> &HashMap<String, ParsedArgument<S, dyn ArgumentType>> {
|
||||
pub fn arguments(
|
||||
&self,
|
||||
) -> &HashMap<String, ParsedArgument<dyn ArgumentType<dyn ArgumentResult>>> {
|
||||
&self.arguments
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
use std::marker::PhantomData;
|
||||
|
||||
use super::string_range::StringRange;
|
||||
|
||||
#[derive(PartialEq, Eq, Hash)]
|
||||
pub struct ParsedArgument<S, T> {
|
||||
pub struct ParsedArgument<T> {
|
||||
range: StringRange,
|
||||
result: T,
|
||||
}
|
||||
|
||||
impl<S, T> ParsedArgument<S, T> {
|
||||
impl<T> ParsedArgument<T> {
|
||||
fn new(start: usize, end: usize, result: T) -> Self {
|
||||
Self {
|
||||
range: StringRange::between(start, end),
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use std::fmt::{Display, Formatter};
|
||||
|
||||
use crate::{
|
||||
arguments::argument_type::ArgumentType,
|
||||
arguments::argument_type::{ArgumentResult, ArgumentType},
|
||||
builder::required_argument_builder::RequiredArgumentBuilder,
|
||||
context::{
|
||||
command_context::CommandContext, command_context_builder::CommandContextBuilder,
|
||||
parsed_argument::ParsedArgument,
|
||||
|
@ -22,14 +23,14 @@ const USAGE_ARGUMENT_CLOSE: &str = ">";
|
|||
#[derive(Hash, PartialEq, Eq, Debug, Clone)]
|
||||
pub struct ArgumentCommandNode<S, T> {
|
||||
name: String,
|
||||
type_: dyn ArgumentType,
|
||||
type_: Box<dyn ArgumentType<dyn ArgumentResult>>,
|
||||
custom_suggestions: dyn SuggestionProvider<S>,
|
||||
// Since Rust doesn't have extending, we put the struct this is extending as the "base" field
|
||||
pub base: BaseCommandNode<S>,
|
||||
}
|
||||
|
||||
impl<S, T> ArgumentCommandNode<S, T> {
|
||||
fn get_type(&self) -> &dyn ArgumentType {
|
||||
fn get_type(&self) -> &dyn ArgumentType<dyn ArgumentResult> {
|
||||
&self.type_
|
||||
}
|
||||
|
||||
|
@ -45,7 +46,7 @@ impl<S, T> CommandNode<S> for ArgumentCommandNode<S, T> {
|
|||
|
||||
fn parse(
|
||||
&self,
|
||||
reader: StringReader,
|
||||
reader: &mut StringReader,
|
||||
context_builder: CommandContextBuilder<S>,
|
||||
) -> Result<(), CommandSyntaxException> {
|
||||
// final int start = reader.getCursor();
|
||||
|
@ -68,7 +69,7 @@ impl<S, T> CommandNode<S> for ArgumentCommandNode<S, T> {
|
|||
fn list_suggestions(
|
||||
&self,
|
||||
context: CommandContext<S>,
|
||||
builder: SuggestionsBuilder,
|
||||
builder: &mut SuggestionsBuilder,
|
||||
) -> Result<Suggestions, CommandSyntaxException> {
|
||||
if self.custom_suggestions.is_none() {
|
||||
self.get_type().list_suggestions(context, builder)
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
use std::collections::HashMap;
|
||||
|
||||
use crate::{
|
||||
arguments::argument_type::{ArgumentResult, ArgumentType},
|
||||
builder::argument_builder::ArgumentBuilder,
|
||||
command::Command,
|
||||
context::{command_context::CommandContext, command_context_builder::CommandContextBuilder},
|
||||
|
@ -13,17 +14,9 @@ use crate::{
|
|||
use super::{argument_command_node::ArgumentCommandNode, literal_command_node::LiteralCommandNode};
|
||||
|
||||
pub struct BaseCommandNode<S> {
|
||||
// private final Map<String, CommandNode<S>> children = new LinkedHashMap<>();
|
||||
// private final Map<String, LiteralCommandNode<S>> literals = new LinkedHashMap<>();
|
||||
// private final Map<String, ArgumentCommandNode<S, ?>> arguments = new LinkedHashMap<>();
|
||||
// private final Predicate<S> requirement;
|
||||
// private final CommandNode<S> redirect;
|
||||
// private final RedirectModifier<S> modifier;
|
||||
// private final boolean forks;
|
||||
// private Command<S> command;
|
||||
children: HashMap<String, dyn CommandNode<S>>,
|
||||
literals: HashMap<String, LiteralCommandNode<S>>,
|
||||
arguments: HashMap<String, ArgumentCommandNode<S, _>>,
|
||||
arguments: HashMap<String, ArgumentCommandNode<S, dyn ArgumentType<dyn ArgumentResult>>>,
|
||||
requirement: Option<dyn Fn(&S) -> bool>,
|
||||
redirect: Option<dyn CommandNode<S>>,
|
||||
modifier: Option<dyn RedirectModifier<S>>,
|
||||
|
|
Loading…
Add table
Reference in a new issue