mirror of
https://github.com/mat-1/azalea.git
synced 2024-09-19 22:52:32 +00:00
start adding brigadier suggestions
This commit is contained in:
parent
8b65d7c95e
commit
2606de9f4c
4 changed files with 186 additions and 1 deletions
|
@ -1,4 +1,5 @@
|
||||||
mod suggestions;
|
mod suggestions;
|
||||||
|
mod suggestions_builder;
|
||||||
|
|
||||||
use crate::context::StringRange;
|
use crate::context::StringRange;
|
||||||
#[cfg(feature = "azalea-buf")]
|
#[cfg(feature = "azalea-buf")]
|
||||||
|
@ -7,7 +8,8 @@ use azalea_buf::McBufWritable;
|
||||||
use azalea_chat::FormattedText;
|
use azalea_chat::FormattedText;
|
||||||
#[cfg(feature = "azalea-buf")]
|
#[cfg(feature = "azalea-buf")]
|
||||||
use std::io::Write;
|
use std::io::Write;
|
||||||
pub use suggestions::*;
|
pub use suggestions::Suggestions;
|
||||||
|
pub use suggestions_builder::SuggestionsBuilder;
|
||||||
|
|
||||||
/// A suggestion given to the user for what they might want to type next.
|
/// A suggestion given to the user for what they might want to type next.
|
||||||
///
|
///
|
||||||
|
|
92
azalea-brigadier/src/suggestion/suggestions_builder.rs
Executable file
92
azalea-brigadier/src/suggestion/suggestions_builder.rs
Executable file
|
@ -0,0 +1,92 @@
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
use crate::context::StringRange;
|
||||||
|
|
||||||
|
use super::{Suggestion, Suggestions};
|
||||||
|
|
||||||
|
pub struct SuggestionsBuilder {
|
||||||
|
input: String,
|
||||||
|
input_lowercase: String,
|
||||||
|
start: usize,
|
||||||
|
remaining: String,
|
||||||
|
remaining_lowercase: String,
|
||||||
|
result: HashSet<Suggestion>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SuggestionsBuilder {
|
||||||
|
pub fn new(input: &str, start: usize) -> Self {
|
||||||
|
Self::new_with_lowercase(input, input.to_lowercase().as_str(), start)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new_with_lowercase(input: &str, input_lowercase: &str, start: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
start,
|
||||||
|
input: input.to_string(),
|
||||||
|
input_lowercase: input_lowercase.to_string(),
|
||||||
|
remaining: input[start..].to_string(),
|
||||||
|
remaining_lowercase: input_lowercase[start..].to_string(),
|
||||||
|
result: HashSet::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn input(&self) -> &str {
|
||||||
|
&self.input
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start(&self) -> usize {
|
||||||
|
self.start
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn remianing(&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) -> Self {
|
||||||
|
if text == self.remaining {
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
self.result.insert(Suggestion {
|
||||||
|
range: StringRange::between(self.start, self.input.len()),
|
||||||
|
text: text.to_string(),
|
||||||
|
tooltip: None,
|
||||||
|
});
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn suggest_with_tooltip(mut self, text: &str, tooltip: String) -> Self {
|
||||||
|
if text == self.remaining {
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
self.result.insert(Suggestion {
|
||||||
|
range: StringRange::between(self.start, self.input.len()),
|
||||||
|
text: text.to_string(),
|
||||||
|
tooltip: Some(tooltip),
|
||||||
|
});
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: integer suggestions
|
||||||
|
// https://github.com/Mojang/brigadier/blob/master/src/main/java/com/mojang/brigadier/suggestion/SuggestionsBuilder.java#L74
|
||||||
|
|
||||||
|
#[allow(clippy::should_implement_trait)]
|
||||||
|
pub fn add(mut self, other: SuggestionsBuilder) -> Self {
|
||||||
|
self.result.extend(other.result);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_offset(&self, start: usize) -> Self {
|
||||||
|
SuggestionsBuilder::new_with_lowercase(&self.input, &self.input_lowercase, start)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn restart(self) -> Self {
|
||||||
|
self.create_offset(self.start)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
#[test]
|
||||||
|
fn apply_insertation_start() {
|
||||||
|
let suggestion = Suggestion::new(StringRange::at(0), "And so I said: ");
|
||||||
|
assert_eq!(suggestion.apply("Hello world!"), "And so I said: Hello world!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn apply_insertation_middle() {
|
||||||
|
let suggestion = Suggestion::new(StringRange::at(6), "small ");
|
||||||
|
assert_eq!(suggestion.apply("Hello world!"), "Hello small world!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn apply_insertation_end() {
|
||||||
|
let suggestion = Suggestion::new(StringRange::at(5), " world!");
|
||||||
|
assert_eq!(suggestion.apply("Hello"), "Hello world!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn apply_replacement_start() {
|
||||||
|
let suggestion = Suggestion::new(StringRange::between(0, 5), "Goodbye");
|
||||||
|
assert_eq!(suggestion.apply("Hello world!"), "Goodbye world!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn apply_replacement_middle() {
|
||||||
|
let suggestion = Suggestion::new(StringRange::between(6, 11), "Alex");
|
||||||
|
assert_eq!(suggestion.apply("Hello world!"), "Hello Alex!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn apply_replacement_end() {
|
||||||
|
let suggestion = Suggestion::new(StringRange::between(6, 12), "Creeper!");
|
||||||
|
assert_eq!(suggestion.apply("Hello world!"), "Hello Creeper!");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn apply_replacement_everything() {
|
||||||
|
let suggestion = Suggestion::new(StringRange::between(0, 12), "Oh dear.");
|
||||||
|
assert_eq!(suggestion.apply("Hello world!"), "Oh dear.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn expand_unchanged() {
|
||||||
|
let suggestion = Suggestion::new(StringRange::at(1), "oo");
|
||||||
|
assert_eq!(suggestion.expand("f", StringRange::at(1)), suggestion);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn expand_left() {
|
||||||
|
let suggestion = Suggestion::new(StringRange::at(1), "oo");
|
||||||
|
assert_eq!(suggestion.expand("f", StringRange::between(0, 1)), Suggestion::new(StringRange::between(0, 1), "foo"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn expand_right() {
|
||||||
|
let suggestion = Suggestion::new(StringRange::at(0), "minecraft:");
|
||||||
|
assert_eq!(suggestion.expand("fish", StringRange::between(0, 4)), Suggestion::new(StringRange::between(0, 4), "minecraft:fish"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn expand_both() {
|
||||||
|
let suggestion = Suggestion::new(StringRange::at(11), "minecraft:");
|
||||||
|
assert_eq!(suggestion.expand("give Steve fish_block", StringRange::between(5, 21)), Suggestion::new(StringRange::between(5, 21), "Steve minecraft:fish_block"));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn expand_replacement() {
|
||||||
|
let suggestion = Suggestion::new(StringRange::between(6, 11), "strangers");
|
||||||
|
assert_eq!(suggestion.expand("Hello world!", StringRange::between(0, 12)), Suggestion::new(StringRange::between(0, 12), "Hello strangers!"));
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
#[test]
|
||||||
|
fn merge_empty() {
|
||||||
|
let merged = Suggestions::merge("foo b", vec![]);
|
||||||
|
assert!(merged.is_empty());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn merge_single() {
|
||||||
|
let suggestions = Suggestions::new(StringRange::at(5), vec![Suggestion::new(StringRange::at(5), "ar")]);
|
||||||
|
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"), Suggestion::new(StringRange::at(5), "az"), Suggestion::new(StringRange::at(5), "Az")]);
|
||||||
|
let b = Suggestions::new(StringRange::between(4, 5), vec![Suggestion::new(StringRange::between(4, 5), "foo"), Suggestion::new(StringRange::between(4, 5), "qux"), Suggestion::new(StringRange::between(4, 5), "apple"), Suggestion::new(StringRange::between(4, 5), "Bar")]);
|
||||||
|
let merged = Suggestions::merge("foo b", vec![a, b]);
|
||||||
|
assert_eq!(merged.get_list(), vec![Suggestion::new(StringRange::between(4, 5), "apple"), Suggestion::new(StringRange::between(4, 5), "ar"), Suggestion::new(StringRange::between(4, 5), "Az"), Suggestion::new(StringRange::between(4, 5), "bar"), Suggestion::new(StringRange::between(4, 5), "Bar"), Suggestion::new(StringRange::between(4, 5), "baz"), Suggestion::new(StringRange::between(4, 5), "bAz"), Suggestion::new(StringRange::between(4, 5), "foo"), Suggestion::new(StringRange::between(4, 5), "qux")]);
|
||||||
|
}
|
Loading…
Reference in a new issue