mirror of
https://github.com/mat-1/azalea.git
synced 2024-09-19 14:42:32 +00:00
a
This commit is contained in:
parent
1b88888151
commit
4ff67d4917
9 changed files with 91 additions and 84 deletions
19
Cargo.lock
generated
19
Cargo.lock
generated
|
@ -72,6 +72,7 @@ name = "azalea-brigadier"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"dyn-clonable",
|
||||
"enum_dispatch",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
|
@ -382,6 +383,18 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum_dispatch"
|
||||
version = "0.3.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bd53b3fde38a39a06b2e66dc282f3e86191e53bd04cc499929c15742beae3df8"
|
||||
dependencies = [
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "flate2"
|
||||
version = "1.0.22"
|
||||
|
@ -717,6 +730,12 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
version = "11.1.3"
|
||||
|
|
|
@ -8,3 +8,4 @@ version = "0.1.0"
|
|||
[dependencies]
|
||||
lazy_static = "^1.4"
|
||||
dyn-clonable = "^0.9"
|
||||
enum_dispatch = "^0.3"
|
||||
|
|
|
@ -10,11 +10,8 @@ use crate::{
|
|||
};
|
||||
use std::fmt::Debug;
|
||||
|
||||
pub struct LiteralArgumentBuilder<'a, S>
|
||||
where
|
||||
,
|
||||
{
|
||||
arguments: RootCommandNode<'a, S>,
|
||||
pub struct LiteralArgumentBuilder<S> {
|
||||
arguments: RootCommandNode<S>,
|
||||
command: Option<Box<dyn Command<S>>>,
|
||||
requirement: Box<dyn Fn(&S) -> bool>,
|
||||
target: Option<Box<dyn CommandNodeTrait<S>>>,
|
||||
|
@ -23,10 +20,7 @@ where
|
|||
literal: String,
|
||||
}
|
||||
|
||||
impl<'a, S> LiteralArgumentBuilder<'a, S>
|
||||
where
|
||||
,
|
||||
{
|
||||
impl<S> LiteralArgumentBuilder<S> {
|
||||
pub fn new(literal: String) -> Self {
|
||||
Self {
|
||||
literal,
|
||||
|
@ -44,10 +38,7 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a, S> ArgumentBuilder<S> for LiteralArgumentBuilder<'a, S>
|
||||
where
|
||||
,
|
||||
{
|
||||
impl<S> ArgumentBuilder<S> for LiteralArgumentBuilder<S> {
|
||||
fn build(self) -> Box<dyn CommandNodeTrait<S>> {
|
||||
let result = LiteralCommandNode::new(self.literal, self.base.build());
|
||||
|
||||
|
|
|
@ -4,11 +4,11 @@ use std::fmt::Debug;
|
|||
/// 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
|
||||
#[derive(Default, Clone)]
|
||||
pub struct CommandDispatcher<'a, S> {
|
||||
root: RootCommandNode<'a, S>,
|
||||
pub struct CommandDispatcher<S> {
|
||||
root: RootCommandNode<S>,
|
||||
}
|
||||
|
||||
impl<S> CommandDispatcher<'_, S> {
|
||||
impl<S> CommandDispatcher<S> {
|
||||
/// The string required to separate individual arguments in an input string
|
||||
///
|
||||
/// See: [`ARGUMENT_SEPARATOR_CHAR`]
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#[macro_use]
|
||||
extern crate lazy_static;
|
||||
|
||||
#[macro_use]
|
||||
extern crate enum_dispatch;
|
||||
|
||||
mod ambiguity_consumer;
|
||||
mod arguments;
|
||||
mod builder;
|
||||
|
|
|
@ -31,18 +31,14 @@ use super::{
|
|||
const USAGE_ARGUMENT_OPEN: &str = "<";
|
||||
const USAGE_ARGUMENT_CLOSE: &str = ">";
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ArgumentCommandNode<'a, S> {
|
||||
pub struct ArgumentCommandNode<S> {
|
||||
name: String,
|
||||
type_: Box<dyn ArgumentType<Into = dyn Any>>,
|
||||
custom_suggestions: Option<&'a dyn SuggestionProvider<S>>,
|
||||
// custom_suggestions: &'a dyn SuggestionProvider<S>,
|
||||
// Since Rust doesn't have extending, we put the struct this is extending as the "base" field
|
||||
pub base: BaseCommandNode<'a, S>,
|
||||
custom_suggestions: Option<Box<dyn SuggestionProvider<S>>>,
|
||||
|
||||
children: HashMap<String, Box<dyn CommandNodeTrait<S>>>,
|
||||
literals: HashMap<String, LiteralCommandNode<'a, S>>,
|
||||
arguments: HashMap<String, ArgumentCommandNode<'a, S>>,
|
||||
literals: HashMap<String, LiteralCommandNode<S>>,
|
||||
arguments: HashMap<String, ArgumentCommandNode<S>>,
|
||||
pub requirement: Box<dyn Fn(&S) -> bool>,
|
||||
redirect: Option<Box<dyn CommandNodeTrait<S>>>,
|
||||
modifier: Option<Box<dyn RedirectModifier<S>>>,
|
||||
|
@ -50,17 +46,17 @@ pub struct ArgumentCommandNode<'a, S> {
|
|||
pub command: Option<Box<dyn Command<S>>>,
|
||||
}
|
||||
|
||||
impl<S> ArgumentCommandNode<'_, S> {
|
||||
impl<S> ArgumentCommandNode<S> {
|
||||
fn get_type(&self) -> &dyn ArgumentType<Into = dyn Any> {
|
||||
self.type_
|
||||
&*self.type_
|
||||
}
|
||||
|
||||
fn custom_suggestions(&self) -> Option<&dyn SuggestionProvider<S>> {
|
||||
self.custom_suggestions
|
||||
fn custom_suggestions(&self) -> &Option<Box<dyn SuggestionProvider<S>>> {
|
||||
&self.custom_suggestions
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, S> CommandNodeTrait<S> for ArgumentCommandNode<'a, S> {
|
||||
impl<S> CommandNodeTrait<S> for ArgumentCommandNode<S> {
|
||||
fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
@ -173,7 +169,7 @@ impl<'a, S> CommandNodeTrait<S> for ArgumentCommandNode<'a, S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> Display for ArgumentCommandNode<'_, S> {
|
||||
impl<S> Display for ArgumentCommandNode<S> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "<argument {}: {}>", self.name, self.type_)
|
||||
}
|
||||
|
|
|
@ -15,43 +15,14 @@ use crate::{
|
|||
use std::ops::Deref;
|
||||
use std::{any::Any, collections::HashMap, fmt::Debug};
|
||||
|
||||
enum CommandNodeEnum<'a, S> {
|
||||
Literal(LiteralCommandNode<'a, S>),
|
||||
Argument(ArgumentCommandNode<'a, S>),
|
||||
Root(RootCommandNode<'a, S>),
|
||||
#[enum_dispatch(CommandNodeTrait)]
|
||||
enum CommandNodeEnum<S> {
|
||||
Literal(LiteralCommandNode<S>),
|
||||
Argument(ArgumentCommandNode<S>),
|
||||
Root(RootCommandNode<S>),
|
||||
}
|
||||
|
||||
impl<'a, S> Deref for CommandNodeEnum<'a, S> {
|
||||
type Target = dyn CommandNodeTrait<S>;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self {
|
||||
CommandNodeEnum::Literal(node) => *node as &Self::Target,
|
||||
CommandNodeEnum::Argument(node) => *node as &Self::Target,
|
||||
CommandNodeEnum::Root(node) => *node as &Self::Target,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> From<LiteralCommandNode<'_, S>> for CommandNodeEnum<'_, S> {
|
||||
fn from(node: LiteralCommandNode<'_, S>) -> Self {
|
||||
CommandNodeEnum::Literal(node)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> From<ArgumentCommandNode<'_, S>> for CommandNodeEnum<'_, S> {
|
||||
fn from(node: ArgumentCommandNode<'_, S>) -> Self {
|
||||
CommandNodeEnum::Argument(node)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> From<RootCommandNode<'_, S>> for CommandNodeEnum<'_, S> {
|
||||
fn from(node: RootCommandNode<'_, S>) -> Self {
|
||||
CommandNodeEnum::Root(node)
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> CommandNodeEnum<'_, S> {
|
||||
impl<S> CommandNodeEnum<S> {
|
||||
fn redirect_modifier(&self) -> Option<&dyn RedirectModifier<S>> {
|
||||
(*self).modifier.as_ref().map(|modifier| modifier.as_ref())
|
||||
}
|
||||
|
@ -92,10 +63,10 @@ impl<S> CommandNodeEnum<'_, S> {
|
|||
}
|
||||
}
|
||||
}
|
||||
pub struct BaseCommandNode<'a, S> {
|
||||
pub struct BaseCommandNode<S> {
|
||||
children: HashMap<String, Box<dyn CommandNodeTrait<S>>>,
|
||||
literals: HashMap<String, LiteralCommandNode<'a, S>>,
|
||||
arguments: HashMap<String, ArgumentCommandNode<'a, S>>,
|
||||
literals: HashMap<String, LiteralCommandNode<S>>,
|
||||
arguments: HashMap<String, ArgumentCommandNode<S>>,
|
||||
pub requirement: Box<dyn Fn(&S) -> bool>,
|
||||
redirect: Option<Box<dyn CommandNodeTrait<S>>>,
|
||||
modifier: Option<Box<dyn RedirectModifier<S>>>,
|
||||
|
@ -118,7 +89,7 @@ pub struct BaseCommandNode<'a, S> {
|
|||
// }
|
||||
// }
|
||||
|
||||
impl<S> Debug for BaseCommandNode<'_, S> {
|
||||
impl<S> Debug for BaseCommandNode<S> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.debug_struct("BaseCommandNode")
|
||||
.field("children", &self.children)
|
||||
|
@ -133,7 +104,7 @@ impl<S> Debug for BaseCommandNode<'_, S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> Default for BaseCommandNode<'_, S> {
|
||||
impl<S> Default for BaseCommandNode<S> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
children: HashMap::new(),
|
||||
|
@ -148,6 +119,7 @@ impl<S> Default for BaseCommandNode<'_, S> {
|
|||
}
|
||||
}
|
||||
|
||||
#[enum_dispatch]
|
||||
pub trait CommandNodeTrait<S> {
|
||||
fn name(&self) -> &str;
|
||||
fn usage_text(&self) -> &str;
|
||||
|
@ -164,4 +136,8 @@ pub trait CommandNodeTrait<S> {
|
|||
fn is_valid_input(&self, input: &str) -> bool;
|
||||
fn create_builder(&self) -> Box<dyn ArgumentBuilder<S>>;
|
||||
fn get_examples(&self) -> Vec<String>;
|
||||
|
||||
fn redirect_modifier(&self) -> Option<&dyn RedirectModifier<S>>;
|
||||
fn can_use(&self, source: S) -> bool;
|
||||
fn add_child(&self, node: &Box<dyn CommandNodeTrait<S>>) -> Result<(), String>;
|
||||
}
|
||||
|
|
|
@ -3,33 +3,45 @@ use crate::{
|
|||
builder::{
|
||||
argument_builder::ArgumentBuilder, literal_argument_builder::LiteralArgumentBuilder,
|
||||
},
|
||||
command::Command,
|
||||
context::{command_context::CommandContext, command_context_builder::CommandContextBuilder},
|
||||
exceptions::{
|
||||
builtin_exceptions::BuiltInExceptions, command_syntax_exception::CommandSyntaxException,
|
||||
},
|
||||
immutable_string_reader::ImmutableStringReader,
|
||||
redirect_modifier::RedirectModifier,
|
||||
string_reader::StringReader,
|
||||
suggestion::{suggestions::Suggestions, suggestions_builder::SuggestionsBuilder},
|
||||
};
|
||||
use std::fmt::Debug;
|
||||
use std::{collections::HashMap, fmt::Debug};
|
||||
|
||||
use super::command_node::{BaseCommandNode, CommandNodeTrait};
|
||||
use super::{
|
||||
argument_command_node::ArgumentCommandNode,
|
||||
command_node::{BaseCommandNode, CommandNodeTrait},
|
||||
};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct LiteralCommandNode<'a, S> {
|
||||
pub struct LiteralCommandNode<S> {
|
||||
literal: String,
|
||||
literal_lowercase: String,
|
||||
// Since Rust doesn't have extending, we put the struct this is extending as the "base" field
|
||||
pub base: BaseCommandNode<'a, S>,
|
||||
|
||||
children: HashMap<String, Box<dyn CommandNodeTrait<S>>>,
|
||||
literals: HashMap<String, LiteralCommandNode<S>>,
|
||||
arguments: HashMap<String, ArgumentCommandNode<S>>,
|
||||
pub requirement: Box<dyn Fn(&S) -> bool>,
|
||||
redirect: Option<Box<dyn CommandNodeTrait<S>>>,
|
||||
modifier: Option<Box<dyn RedirectModifier<S>>>,
|
||||
forks: bool,
|
||||
pub command: Option<Box<dyn Command<S>>>,
|
||||
}
|
||||
|
||||
impl<'a, S> LiteralCommandNode<'a, S> {
|
||||
pub fn new(literal: String, base: BaseCommandNode<'a, S>) -> Self {
|
||||
impl<S> LiteralCommandNode<S> {
|
||||
pub fn new(literal: String) -> Self {
|
||||
let literal_lowercase = literal.to_lowercase();
|
||||
Self {
|
||||
literal,
|
||||
literal_lowercase,
|
||||
base,
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -54,7 +66,7 @@ impl<'a, S> LiteralCommandNode<'a, S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> CommandNodeTrait<S> for LiteralCommandNode<'_, S> {
|
||||
impl<S> CommandNodeTrait<S> for LiteralCommandNode<S> {
|
||||
fn name(&self) -> &str {
|
||||
&self.literal
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ use super::{
|
|||
use crate::{
|
||||
arguments::argument_type::ArgumentType,
|
||||
builder::argument_builder::ArgumentBuilder,
|
||||
command::Command,
|
||||
context::{command_context::CommandContext, command_context_builder::CommandContextBuilder},
|
||||
exceptions::{
|
||||
builtin_exceptions::BuiltInExceptions, command_syntax_exception::CommandSyntaxException,
|
||||
|
@ -16,16 +17,24 @@ use crate::{
|
|||
};
|
||||
use std::{
|
||||
any::Any,
|
||||
collections::HashMap,
|
||||
fmt::{Debug, Display, Formatter},
|
||||
};
|
||||
|
||||
#[derive(Clone, Default, Debug)]
|
||||
pub struct RootCommandNode<'a, S> {
|
||||
#[derive(Default)]
|
||||
pub struct RootCommandNode<S> {
|
||||
// Since Rust doesn't have extending, we put the struct this is extending as the "base" field
|
||||
pub base: BaseCommandNode<'a, S>,
|
||||
children: HashMap<String, Box<dyn CommandNodeTrait<S>>>,
|
||||
literals: HashMap<String, LiteralCommandNode<S>>,
|
||||
arguments: HashMap<String, ArgumentCommandNode<S>>,
|
||||
pub requirement: Box<dyn Fn(&S) -> bool>,
|
||||
redirect: Option<Box<dyn CommandNodeTrait<S>>>,
|
||||
modifier: Option<Box<dyn RedirectModifier<S>>>,
|
||||
forks: bool,
|
||||
pub command: Option<Box<dyn Command<S>>>,
|
||||
}
|
||||
|
||||
impl<S> CommandNodeTrait<S> for RootCommandNode<'_, S> {
|
||||
impl<S> CommandNodeTrait<S> for RootCommandNode<S> {
|
||||
fn name(&self) -> &str {
|
||||
""
|
||||
}
|
||||
|
@ -63,7 +72,7 @@ impl<S> CommandNodeTrait<S> for RootCommandNode<'_, S> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<S> Display for RootCommandNode<'_, S> {
|
||||
impl<S> Display for RootCommandNode<S> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "<root>")
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue