mirror of
https://github.com/mat-1/azalea.git
synced 2025-08-02 06:16:04 +00:00
adfsfasdfaSDQAWERTERYTUYghyubnjnrdfxcv etgvbhy0ujn-
This commit is contained in:
parent
60b129b3a6
commit
cc4fe62fc8
14 changed files with 299 additions and 29 deletions
|
@ -7,7 +7,9 @@ use crate::{
|
|||
};
|
||||
|
||||
pub trait Types {
|
||||
fn bool(value: bool) -> Self;
|
||||
fn bool(value: bool) -> Self
|
||||
where
|
||||
Self: Sized;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -28,7 +30,7 @@ enum BrigadierTypes {
|
|||
pub trait ArgumentType<T>
|
||||
where
|
||||
Self: Sized,
|
||||
T: Types,
|
||||
T: Types + ?Sized,
|
||||
{
|
||||
// T parse(StringReader reader) throws CommandSyntaxException;
|
||||
|
||||
|
|
|
@ -33,13 +33,13 @@ where
|
|||
// builder.suggest("false");
|
||||
// }
|
||||
// return builder.buildFuture();
|
||||
if "true".starts_with(builder.get_remaining_lower_case()) {
|
||||
if "true".starts_with(builder.remaining_lowercase()) {
|
||||
builder.suggest("true");
|
||||
}
|
||||
if "false".starts_with(builder.get_remaining_lower_case()) {
|
||||
if "false".starts_with(builder.remaining_lowercase()) {
|
||||
builder.suggest("false");
|
||||
}
|
||||
Ok(builder.build_future())
|
||||
Ok(builder.build())
|
||||
}
|
||||
|
||||
fn get_examples(&self) -> Vec<String> {
|
||||
|
|
|
@ -14,17 +14,20 @@ pub struct CommandContext<'a, S, T> {
|
|||
command: &'a dyn Command<S, T>,
|
||||
arguments: HashMap<String, ParsedArgument<T>>,
|
||||
root_node: &'a dyn CommandNode<S, T>,
|
||||
nodes: Vec<ParsedCommandNode<'a, S, T>>,
|
||||
nodes: Vec<ParsedCommandNode<S, T>>,
|
||||
range: StringRange,
|
||||
child: Option<CommandContext<'a, S, T>>,
|
||||
child: Option<&'a CommandContext<'a, S, T>>,
|
||||
modifier: Option<&'a dyn RedirectModifier<S, T>>,
|
||||
forks: bool,
|
||||
}
|
||||
|
||||
impl<S, T> CommandContext<'_, S, T> {
|
||||
impl<S, T> CommandContext<'_, S, T>
|
||||
where
|
||||
S: PartialEq,
|
||||
{
|
||||
pub fn clone_for(&self, source: S) -> Self {
|
||||
if self.source == source {
|
||||
return self.clone();
|
||||
return *self;
|
||||
}
|
||||
Self {
|
||||
source,
|
||||
|
|
|
@ -28,7 +28,7 @@ use super::{
|
|||
pub struct CommandContextBuilder<'a, S, T> {
|
||||
arguments: HashMap<String, ParsedArgument<T>>,
|
||||
root_node: &'a dyn CommandNode<S, T>,
|
||||
nodes: Vec<ParsedCommandNode<'a, S, T>>,
|
||||
nodes: Vec<ParsedCommandNode<S, T>>,
|
||||
dispatcher: CommandDispatcher<'a, S, T>,
|
||||
source: S,
|
||||
command: Box<dyn Command<S, T>>,
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use super::string_range::StringRange;
|
||||
|
||||
#[derive(PartialEq, Eq, Hash)]
|
||||
#[derive(PartialEq, Eq, Hash, Clone)]
|
||||
pub struct ParsedArgument<T> {
|
||||
range: StringRange,
|
||||
// T is an item in an enum
|
||||
|
|
|
@ -1,14 +1,13 @@
|
|||
use super::string_range::StringRange;
|
||||
use crate::tree::command_node::CommandNode;
|
||||
|
||||
#[derive(Hash, PartialEq, Eq, Debug, Clone)]
|
||||
pub struct ParsedCommandNode<'a, S, T> {
|
||||
node: &'a dyn CommandNode<S, T>,
|
||||
pub struct ParsedCommandNode<S, T> {
|
||||
node: Box<dyn CommandNode<S, T>>,
|
||||
range: StringRange,
|
||||
}
|
||||
|
||||
impl<S, T> ParsedCommandNode<'_, S, T> {
|
||||
fn new(node: &dyn CommandNode<S, T>, range: StringRange) -> Self {
|
||||
impl<S, T> ParsedCommandNode<S, T> {
|
||||
fn new(node: dyn CommandNode<S, T>, range: StringRange) -> Self {
|
||||
Self { node, range }
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::cmp;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct StringRange {
|
||||
start: usize,
|
||||
end: usize,
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
use std::rc::Rc;
|
||||
|
||||
#[derive(Debug, Clone, Hash, PartialEq, Eq)]
|
||||
pub struct Message(Rc<String>);
|
||||
|
||||
impl Message {
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
use std::cmp;
|
||||
|
||||
use crate::{context::string_range::StringRange, message::Message};
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct Suggestion {
|
||||
range: StringRange,
|
||||
text: String,
|
||||
tooltip: Option<Message>,
|
||||
}
|
||||
|
||||
impl Suggestion {
|
||||
pub fn new(range: StringRange, text: String) -> Suggestion {
|
||||
Suggestion {
|
||||
range,
|
||||
text,
|
||||
tooltip: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new_with_tooltip(range: StringRange, text: String, tooltip: Message) -> Suggestion {
|
||||
Suggestion {
|
||||
range,
|
||||
text,
|
||||
tooltip: Some(tooltip),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn range(&self) -> &StringRange {
|
||||
&self.range
|
||||
}
|
||||
|
||||
pub fn text(&self) -> &String {
|
||||
&self.text
|
||||
}
|
||||
|
||||
pub fn tooltip(&self) -> Option<&Message> {
|
||||
self.tooltip.as_ref()
|
||||
}
|
||||
|
||||
pub fn apply(&self, input: &str) -> String {
|
||||
if self.range.start() == 0 && self.range.end() == input.len() {
|
||||
return self.text.clone();
|
||||
}
|
||||
let mut result = String::new();
|
||||
if self.range.start() > 0 {
|
||||
result.push_str(&input[0..self.range.start()]);
|
||||
}
|
||||
result.push_str(&self.text);
|
||||
if self.range.end() < input.len() {
|
||||
result.push_str(&input[self.range.end()..]);
|
||||
}
|
||||
result
|
||||
}
|
||||
|
||||
pub fn expand(&self, command: &str, range: StringRange) -> Suggestion {
|
||||
if range == self.range {
|
||||
return self.clone();
|
||||
}
|
||||
let mut result = String::new();
|
||||
if range.start() < self.range.start() {
|
||||
result.push_str(&command[range.start()..self.range.start()]);
|
||||
}
|
||||
result.push_str(&self.text);
|
||||
if range.end() > self.range.end() {
|
||||
result.push_str(&command[self.range.end()..range.end()]);
|
||||
}
|
||||
Suggestion {
|
||||
range,
|
||||
text: result,
|
||||
tooltip: self.tooltip.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn compare_ignore_case(&self, b: &Suggestion) -> cmp::Ordering {
|
||||
self.text.to_lowercase().cmp(&b.text.to_lowercase())
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Suggestion {
|
||||
fn partial_cmp(&self, other: &Suggestion) -> Option<cmp::Ordering> {
|
||||
Some(self.text.cmp(&other.text))
|
||||
}
|
||||
}
|
||||
|
||||
impl Ord for Suggestion {
|
||||
fn cmp(&self, other: &Suggestion) -> cmp::Ordering {
|
||||
self.text.cmp(&other.text)
|
||||
}
|
||||
}
|
|
@ -1 +1,59 @@
|
|||
use std::cmp;
|
||||
|
||||
use crate::{context::string_range::StringRange, message::Message};
|
||||
|
||||
pub struct Suggestions {}
|
||||
|
||||
// #[cfg(test)]
|
||||
// mod tests {
|
||||
// use crate::suggestion::suggestion::Suggestion;
|
||||
|
||||
// use super::*;
|
||||
|
||||
// #[test]
|
||||
// fn merge_empty() {
|
||||
// let merged = Suggestions::merge("foo b", vec![]);
|
||||
// assert_eq!(merged.is_empty(), true);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn merge_single() {
|
||||
// let suggestions = Suggestions::new(StringRange::at(5), "ar".to_string());
|
||||
// let merged = Suggestions::merge("foo b", vec![suggestions]);
|
||||
// assert_eq!(merged, suggestions);
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn merge_multiple() {
|
||||
// let a = Suggestions::new(
|
||||
// StringRange::at(5),
|
||||
// vec![
|
||||
// Suggestion::new(StringRange::at(5), "ar".to_string()),
|
||||
// Suggestion::new(StringRange::at(5), "az".to_string()),
|
||||
// Suggestion::new(StringRange::at(5), "Az".to_string()),
|
||||
// ],
|
||||
// );
|
||||
// let b = Suggestions::new(
|
||||
// StringRange::between(4, 5),
|
||||
// vec![
|
||||
// Suggestion::new(StringRange::between(4, 5), "foo".to_string()),
|
||||
// Suggestion::new(StringRange::between(4, 5), "qux".to_string()),
|
||||
// Suggestion::new(StringRange::between(4, 5), "apple".to_string()),
|
||||
// Suggestion::new(StringRange::between(4, 5), "Bar".to_string()),
|
||||
// ],
|
||||
// );
|
||||
// let merged = Suggestions::merge("foo b", vec![a, b]);
|
||||
// assert_eq!(
|
||||
// merged.get_list(),
|
||||
// vec![
|
||||
// Suggestion::new(StringRange::between(4, 5), "apple".to_string()),
|
||||
// Suggestion::new(StringRange::between(4, 5), "bar".to_string()),
|
||||
// Suggestion::new(StringRange::between(4, 5), "Bar".to_string()),
|
||||
// Suggestion::new(StringRange::between(4, 5), "baz".to_string()),
|
||||
// Suggestion::new(StringRange::between(4, 5), "bAz".to_string()),
|
||||
// Suggestion::new(StringRange::between(4, 5), "foo".to_string()),
|
||||
// Suggestion::new(StringRange::between(4, 5), "qux".to_string()),
|
||||
// ]
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
|
|
@ -1 +1,114 @@
|
|||
pub struct SuggestionsBuilder {}
|
||||
use crate::context::string_range::StringRange;
|
||||
|
||||
use super::{suggestion::Suggestion, suggestions::Suggestions};
|
||||
|
||||
pub struct SuggestionsBuilder {
|
||||
input: String,
|
||||
input_lowercase: String,
|
||||
start: usize,
|
||||
remaining: String,
|
||||
remaining_lowercase: String,
|
||||
result: Vec<Suggestion>,
|
||||
}
|
||||
|
||||
impl SuggestionsBuilder {
|
||||
pub fn new_with_lowercase(
|
||||
input: String,
|
||||
input_lowercase: String,
|
||||
start: usize,
|
||||
) -> SuggestionsBuilder {
|
||||
SuggestionsBuilder {
|
||||
input,
|
||||
input_lowercase,
|
||||
start,
|
||||
remaining: input.get(start..).unwrap().to_string(),
|
||||
remaining_lowercase: input_lowercase.get(start..).unwrap().to_string(),
|
||||
result: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn new(input: String, start: usize) -> SuggestionsBuilder {
|
||||
SuggestionsBuilder::new_with_lowercase(input, input.to_lowercase(), start)
|
||||
}
|
||||
|
||||
pub fn input(&self) -> &str {
|
||||
&self.input
|
||||
}
|
||||
|
||||
pub fn start(&self) -> usize {
|
||||
self.start
|
||||
}
|
||||
|
||||
pub fn remaining(&self) -> &str {
|
||||
&self.remaining
|
||||
}
|
||||
|
||||
pub fn remaining_lowercase(&self) -> &str {
|
||||
&self.remaining_lowercase
|
||||
}
|
||||
|
||||
pub fn build(&self) -> Suggestions {
|
||||
Suggestions::create(self.input(), self.result)
|
||||
}
|
||||
|
||||
pub fn suggest(&mut self, text: &str) -> &mut SuggestionsBuilder {
|
||||
if text == self.remaining {
|
||||
return self;
|
||||
}
|
||||
self.result.push(Suggestion::new(
|
||||
StringRange::between(self.start, self.input.len()),
|
||||
text,
|
||||
));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn suggest_with_tooltip(&mut self, text: &str, tooltip: &str) -> &mut SuggestionsBuilder {
|
||||
if text == self.remaining {
|
||||
return self;
|
||||
}
|
||||
self.result.push(Suggestion::new_with_tooltip(
|
||||
StringRange::between(self.start, self.input.len()),
|
||||
text,
|
||||
tooltip,
|
||||
));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn suggest_with_value(&mut self, value: i32) -> &mut SuggestionsBuilder {
|
||||
self.result.push(IntegerSuggestion::new(
|
||||
StringRange::between(self.start, self.input.len()),
|
||||
value,
|
||||
));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn suggest_with_value_and_tooltip(
|
||||
&mut self,
|
||||
value: i32,
|
||||
tooltip: &str,
|
||||
) -> &mut SuggestionsBuilder {
|
||||
self.result.push(IntegerSuggestion::new_with_tooltip(
|
||||
StringRange::between(self.start, self.input.len()),
|
||||
value,
|
||||
tooltip,
|
||||
));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add(&mut self, other: &SuggestionsBuilder) -> &mut SuggestionsBuilder {
|
||||
self.result.extend(other.result.iter().cloned());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn create_offset(&self, start: usize) -> SuggestionsBuilder {
|
||||
SuggestionsBuilder::new_with_lowercase(
|
||||
self.input.clone(),
|
||||
self.input_lowercase.clone(),
|
||||
start,
|
||||
)
|
||||
}
|
||||
|
||||
pub fn restart(&self) -> SuggestionsBuilder {
|
||||
self.create_offset(self.start)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,13 +1,14 @@
|
|||
use std::fmt::{Display, Formatter};
|
||||
|
||||
use crate::{
|
||||
arguments::argument_type::ArgumentType,
|
||||
arguments::argument_type::{ArgumentType, Types},
|
||||
builder::required_argument_builder::RequiredArgumentBuilder,
|
||||
context::{
|
||||
command_context::CommandContext, command_context_builder::CommandContextBuilder,
|
||||
parsed_argument::ParsedArgument,
|
||||
},
|
||||
exceptions::command_syntax_exception::CommandSyntaxException,
|
||||
immutable_string_reader::ImmutableStringReader,
|
||||
string_reader::StringReader,
|
||||
suggestion::{
|
||||
suggestion_provider::SuggestionProvider, suggestions::Suggestions,
|
||||
|
@ -20,11 +21,15 @@ use super::command_node::{BaseCommandNode, CommandNode};
|
|||
const USAGE_ARGUMENT_OPEN: &str = "<";
|
||||
const USAGE_ARGUMENT_CLOSE: &str = ">";
|
||||
|
||||
#[derive(Hash, PartialEq, Eq, Debug, Clone)]
|
||||
pub struct ArgumentCommandNode<'a, S, T> {
|
||||
pub struct ArgumentCommandNode<'a, S, T>
|
||||
where
|
||||
// each argument command node has its own different type
|
||||
T: ArgumentType<dyn Types>,
|
||||
{
|
||||
name: String,
|
||||
type_: &'a T,
|
||||
custom_suggestions: &'a dyn SuggestionProvider<S, T>,
|
||||
custom_suggestions: Option<&'a dyn SuggestionProvider<S, T>>,
|
||||
// custom_suggestions: &'a dyn SuggestionProvider<S, T>,
|
||||
// Since Rust doesn't have extending, we put the struct this is extending as the "base" field
|
||||
pub base: BaseCommandNode<'a, S, T>,
|
||||
}
|
||||
|
@ -34,12 +39,12 @@ impl<S, T> ArgumentCommandNode<'_, S, T> {
|
|||
&self.type_
|
||||
}
|
||||
|
||||
fn custom_suggestions(&self) -> &dyn SuggestionProvider<S, T> {
|
||||
&self.custom_suggestions
|
||||
fn custom_suggestions(&self) -> Option<&dyn SuggestionProvider<S, T>> {
|
||||
self.custom_suggestions
|
||||
}
|
||||
}
|
||||
|
||||
impl<S, T> CommandNode<S, T> for ArgumentCommandNode<'_, S, T> {
|
||||
impl<'a, S, T> CommandNode<S, T> for ArgumentCommandNode<'a, S, T> {
|
||||
fn name(&self) -> &str {
|
||||
&self.name
|
||||
}
|
||||
|
@ -56,7 +61,7 @@ impl<S, T> CommandNode<S, T> for ArgumentCommandNode<'_, S, T> {
|
|||
// contextBuilder.withArgument(name, parsed);
|
||||
// contextBuilder.withNode(this, parsed.getRange());
|
||||
|
||||
let start = reader.get_cursor();
|
||||
let start = reader.cursor();
|
||||
let result = self.get_type().parse(reader)?;
|
||||
let parsed = ParsedArgument::new(start, reader.get_cursor(), result);
|
||||
|
||||
|
@ -112,7 +117,7 @@ impl<S, T> CommandNode<S, T> for ArgumentCommandNode<'_, S, T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for ArgumentCommandNode<'_, String, String> {
|
||||
impl Display for ArgumentCommandNode<'_, (), (), ()> {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "<argument {}: {}>", self.name, self.type_)
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ pub trait CommandNode<S, T> {
|
|||
fn usage_text(&self) -> &str;
|
||||
fn parse(
|
||||
&self,
|
||||
reader: StringReader,
|
||||
reader: &mut StringReader,
|
||||
context_builder: CommandContextBuilder<S, T>,
|
||||
) -> Result<(), CommandSyntaxException>;
|
||||
fn list_suggestions(
|
||||
|
|
|
@ -11,7 +11,6 @@ use crate::{
|
|||
|
||||
use super::command_node::{BaseCommandNode, CommandNode};
|
||||
|
||||
#[derive(Hash, PartialEq, Eq, Debug, Clone)]
|
||||
pub struct RootCommandNode<'a, S, T> {
|
||||
// Since Rust doesn't have extending, we put the struct this is extending as the "base" field
|
||||
pub base: BaseCommandNode<'a, S, T>,
|
||||
|
|
Loading…
Add table
Reference in a new issue