1
2
Fork 0
mirror of https://github.com/mat-1/azalea.git synced 2025-08-02 14:26:04 +00:00

add tests for to_ansi

This commit is contained in:
mat 2021-12-09 17:28:18 +00:00
parent 4bf2ef15f9
commit 577c2aa544
3 changed files with 81 additions and 42 deletions

View file

@ -23,12 +23,14 @@ impl Component {
// if it's primitive, make it a text component // if it's primitive, make it a text component
if !json.is_array() && !json.is_object() { if !json.is_array() && !json.is_object() {
component = Component::TextComponent(TextComponent::new(json.to_string())); component = Component::TextComponent(TextComponent::new(
json.as_str().unwrap_or("").to_string(),
));
} }
// if it's an object, do things with { text } and stuff // if it's an object, do things with { text } and stuff
else if json.is_object() { else if json.is_object() {
if json.get("text").is_some() { if json.get("text").is_some() {
let text = json.get("text").unwrap().to_string(); let text = json.get("text").unwrap().as_str().unwrap_or("").to_string();
component = Component::TextComponent(TextComponent::new(text)); component = Component::TextComponent(TextComponent::new(text));
} else if json.get("translate").is_some() { } else if json.get("translate").is_some() {
let translate = json.get("translate").unwrap().to_string(); let translate = json.get("translate").unwrap().to_string();
@ -133,6 +135,11 @@ impl Component {
} }
} }
// var5_17.setStyle((Style)jsonDeserializationContext.deserialize(jsonElement, Style.class));
let style = Style::deserialize(json);
println!("set style to {:?}", style);
component.get_base().style = style;
return Ok(component); return Ok(component);
} }
// ok so it's not an object, if it's an array deserialize every item // ok so it's not an object, if it's an array deserialize every item
@ -172,34 +179,42 @@ impl Component {
pub fn to_ansi(&self, parent_style: Option<&mut Style>) -> String { pub fn to_ansi(&self, parent_style: Option<&mut Style>) -> String {
// the siblings of this component // the siblings of this component
let base; let base;
let mut text; let component_text: String;
let mut styled_component = String::new();
match self { match self {
Self::TextComponent(c) => { Self::TextComponent(c) => {
base = &c.base; base = &c.base;
text = c.text.clone(); component_text = c.text.clone();
} }
Self::TranslatableComponent(c) => { Self::TranslatableComponent(c) => {
base = &c.base; base = &c.base;
text = c.key.clone(); component_text = c.key.clone();
} }
}; };
// we'll fall back to this if there's no parent style // we'll fall back to this if there's no parent style
let default_style = &mut Style::new(); let default_style = &mut Style::new();
// apply the style of this component to the current style // if it's the base style, that means we add a style reset at the end
let is_base_style = parent_style.is_none();
let current_style: &mut Style = parent_style.unwrap_or(default_style); let current_style: &mut Style = parent_style.unwrap_or(default_style);
let new_style = &base.style;
current_style.apply(new_style);
let ansi_text = base.style.compare_ansi(&new_style); // the old style is current_style and the new style is the base.style
let ansi_text = current_style.compare_ansi(&base.style);
current_style.apply(&base.style);
text.push_str(&ansi_text); styled_component.push_str(&ansi_text);
styled_component.push_str(&component_text);
for sibling in &base.siblings { for sibling in &base.siblings {
text.push_str(&sibling.to_ansi(Some(current_style))); styled_component.push_str(&sibling.to_ansi(Some(current_style)));
} }
text.clone() if is_base_style {
styled_component.push_str("\x1b[m");
}
styled_component.clone()
} }
} }

View file

@ -2,8 +2,8 @@ use std::collections::HashMap;
use serde_json::Value; use serde_json::Value;
#[derive(Clone, PartialEq)] #[derive(Clone, PartialEq, Debug)]
struct TextColor { pub struct TextColor {
value: u32, value: u32,
name: Option<String>, name: Option<String>,
} }
@ -29,21 +29,21 @@ impl TextColor {
// private static final Map<String, TextColor> NAMED_COLORS = (Map)LEGACY_FORMAT_TO_COLOR.values().stream().collect(ImmutableMap.toImmutableMap(textColor -> textColor.name, Function.identity())); // private static final Map<String, TextColor> NAMED_COLORS = (Map)LEGACY_FORMAT_TO_COLOR.values().stream().collect(ImmutableMap.toImmutableMap(textColor -> textColor.name, Function.identity()));
let mut LEGACY_FORMAT_TO_COLOR = HashMap::new(); let mut LEGACY_FORMAT_TO_COLOR = HashMap::new();
let mut NAMED_COLORS = HashMap::new(); let mut NAMED_COLORS = HashMap::new();
for i in ChatFormatting::FORMATTERS { for formatter in &ChatFormatting::FORMATTERS {
if i.is_format && i != ChatFormatting::RESET { if !formatter.is_format && *formatter != ChatFormatting::RESET {
LEGACY_FORMAT_TO_COLOR.insert( LEGACY_FORMAT_TO_COLOR.insert(
i, formatter,
TextColor { TextColor {
value: i.color.unwrap(), value: formatter.color.unwrap(),
name: Some(i.name.to_string()), name: Some(formatter.name.to_string()),
}, },
); );
} }
} }
for i in LEGACY_FORMAT_TO_COLOR.values() { for color in LEGACY_FORMAT_TO_COLOR.values() {
NAMED_COLORS.insert(i.name.unwrap(), i.clone()); NAMED_COLORS.insert(color.name.as_ref().unwrap(), color.clone());
} }
let color = NAMED_COLORS.get(&value); let color = NAMED_COLORS.get(&value.to_ascii_uppercase());
if color.is_some() { if color.is_some() {
return Ok(color.unwrap().clone()); return Ok(color.unwrap().clone());
} }
@ -55,9 +55,22 @@ impl TextColor {
} }
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn text_color_named_colors() {
assert_eq!(
TextColor::parse("red".to_string()).unwrap().value,
16733525u32
);
}
}
const PREFIX_CODE: char = '\u{00a7}'; const PREFIX_CODE: char = '\u{00a7}';
#[derive(Clone, PartialEq, Eq, Hash)] #[derive(Clone, PartialEq, Eq, Hash, Debug)]
struct ChatFormatting<'a> { struct ChatFormatting<'a> {
name: &'a str, name: &'a str,
code: char, code: char,
@ -140,11 +153,11 @@ impl TextColor {
Self { value, name } Self { value, name }
} }
fn format(&self) -> String { pub fn format(&self) -> String {
format!("#{:06X}", self.value) format!("#{:06X}", self.value)
} }
fn to_string(&self) -> String { pub fn to_string(&self) -> String {
if let Some(name) = &self.name { if let Some(name) = &self.name {
name.clone() name.clone()
} else { } else {
@ -153,7 +166,7 @@ impl TextColor {
} }
} }
#[derive(Clone)] #[derive(Clone, Debug)]
pub struct Style { pub struct Style {
// @Nullable // @Nullable
// final TextColor color; // final TextColor color;
@ -177,12 +190,12 @@ pub struct Style {
// final ResourceLocation font; // final ResourceLocation font;
// these are options instead of just bools because None is different than false in this case // these are options instead of just bools because None is different than false in this case
color: Option<TextColor>, pub color: Option<TextColor>,
bold: Option<bool>, pub bold: Option<bool>,
italic: Option<bool>, pub italic: Option<bool>,
underlined: Option<bool>, pub underlined: Option<bool>,
strikethrough: Option<bool>, pub strikethrough: Option<bool>,
obfuscated: Option<bool>, pub obfuscated: Option<bool>,
} }
impl Style { impl Style {
@ -197,7 +210,7 @@ impl Style {
} }
} }
fn deserialize(json: Value) { pub fn deserialize(json: &Value) -> Style {
// if (jsonElement.isJsonObject()) { // if (jsonElement.isJsonObject()) {
// JsonObject jsonObject = jsonElement.getAsJsonObject(); // JsonObject jsonObject = jsonElement.getAsJsonObject();
// if (jsonObject == null) { // if (jsonObject == null) {
@ -216,18 +229,28 @@ impl Style {
// return new Style(textColor, bl, bl2, bl3, bl4, bl5, clickEvent, hoverEvent, string, resourceLocation); // return new Style(textColor, bl, bl2, bl3, bl4, bl5, clickEvent, hoverEvent, string, resourceLocation);
// } // }
// return null; // return null;
if json.is_object() { return if json.is_object() {
let json_object = json.as_object().unwrap(); let json_object = json.as_object().unwrap();
let bold = json_object.get("bold").and_then(|v| v.as_bool()); let bold = json_object.get("bold").and_then(|v| v.as_bool());
let italic = json_object.get("italic").and_then(|v| v.as_bool()); let italic = json_object.get("italic").and_then(|v| v.as_bool());
let underlined = json_object.get("underlined").and_then(|v| v.as_bool()); let underlined = json_object.get("underlined").and_then(|v| v.as_bool());
let strikethrough = json_object.get("strikethrough").and_then(|v| v.as_bool()); let strikethrough = json_object.get("strikethrough").and_then(|v| v.as_bool());
let obfuscated = json_object.get("obfuscated").and_then(|v| v.as_bool()); let obfuscated = json_object.get("obfuscated").and_then(|v| v.as_bool());
let color = json_object let color: Option<TextColor> = json_object
.get("color") .get("color")
.and_then(|v| v.as_string()) .and_then(|v| v.as_str())
.and_then(|v| TextColor::parse(v)); .and_then(|v| TextColor::parse(v.to_string()).ok());
} Style {
color,
bold,
italic,
underlined,
strikethrough,
obfuscated,
}
} else {
Style::new()
};
} }
/// Check if a style has no attributes set /// Check if a style has no attributes set
@ -270,7 +293,7 @@ impl Style {
let mut ansi_codes = String::new(); let mut ansi_codes = String::new();
let before = if should_reset { let before = if should_reset {
ansi_codes.push_str("\x1b[0m"); ansi_codes.push_str("\x1b[m");
Style::new() Style::new()
} else { } else {
self.clone() self.clone()
@ -321,7 +344,7 @@ impl Style {
)); ));
} }
return "".to_string(); ansi_codes
} }
/// Apply another style to this one /// Apply another style to this one

View file

@ -6,10 +6,11 @@ fn test() {
let j: Value = serde_json::from_str( let j: Value = serde_json::from_str(
r#"{ r#"{
"text": "hello", "text": "hello",
"color": "red" "color": "red",
"bold": true
}"#, }"#,
) )
.unwrap(); .unwrap();
let component = Component::new(&j).unwrap(); let component = Component::new(&j).unwrap();
println!("println: {}", component.to_ansi(None)); assert_eq!(component.to_ansi(None), "\x1b[38;2;255;85;85mhello\x1b[m");
} }