diff options
author | Zhenhui Xie <xiezh0831@yahoo.co.jp> | 2020-04-11 00:23:20 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-04-10 18:23:20 +0200 |
commit | b11fe2ad30a3506541dacf32821d7fd70125e9bf (patch) | |
tree | dbad9ed03ebc12291b7cd28bece6adf3141a87ff | |
parent | d21e1b897046fd4e4bbee4626c30eaf2a5fd3849 (diff) |
fix: Fix variable styles in string formatter (#1069)
* fix: Fix styling in variables
* fix: Fix clippy
* fix: Allow passing styles down to segments with no style
* fix: Fix clippy
-rw-r--r-- | src/formatter/string_formatter.rs | 82 | ||||
-rw-r--r-- | src/segment.rs | 5 |
2 files changed, 83 insertions, 4 deletions
diff --git a/src/formatter/string_formatter.rs b/src/formatter/string_formatter.rs index 70938973f..8f33ce9ef 100644 --- a/src/formatter/string_formatter.rs +++ b/src/formatter/string_formatter.rs @@ -9,7 +9,19 @@ use crate::segment::Segment; use super::model::*; use super::parser::{parse, Rule}; -type VariableMapType = BTreeMap<String, Option<Vec<Segment>>>; +#[derive(Clone)] +enum VariableValue { + Plain(String), + Styled(Vec<Segment>), +} + +impl Default for VariableValue { + fn default() -> Self { + VariableValue::Plain(String::new()) + } +} + +type VariableMapType = BTreeMap<String, Option<VariableValue>>; pub struct StringFormatter<'a> { format: Vec<FormatElement<'a>>, @@ -30,7 +42,7 @@ impl<'a> StringFormatter<'a> { /// Maps variable name to its value pub fn map(mut self, mapper: impl Fn(&str) -> Option<String> + Sync) -> Self { self.variables.par_iter_mut().for_each(|(key, value)| { - *value = mapper(key).map(|value| vec![_new_segment(key.to_string(), value, None)]); + *value = mapper(key).map(VariableValue::Plain); }); self } @@ -41,7 +53,7 @@ impl<'a> StringFormatter<'a> { mapper: impl Fn(&str) -> Option<Vec<Segment>> + Sync, ) -> Self { self.variables.par_iter_mut().for_each(|(key, value)| { - *value = mapper(key); + *value = mapper(key).map(VariableValue::Styled); }); self } @@ -95,7 +107,25 @@ impl<'a> StringFormatter<'a> { } FormatElement::Variable(name) => variables .get(name.as_ref()) - .map(|segments| segments.clone().unwrap_or_default()) + .map(|segments| { + let value = segments.clone().unwrap_or_default(); + match value { + VariableValue::Styled(segments) => segments + .into_iter() + .map(|mut segment| { + if !segment.has_style() { + if let Some(style) = style { + segment.set_style(style); + } + } + segment + }) + .collect(), + VariableValue::Plain(text) => { + vec![_new_segment(name.to_string(), text, style)] + } + } + }) .unwrap_or_default(), }; result.append(&mut segments); @@ -237,6 +267,50 @@ mod tests { } #[test] + fn test_styled_variable_as_text() { + const FORMAT_STR: &str = "[$var](red bold)"; + let var_style = Some(Color::Red.bold()); + + let formatter = StringFormatter::new(FORMAT_STR) + .unwrap() + .map(|variable| match variable { + "var" => Some("text".to_owned()), + _ => None, + }); + let result = formatter.parse(None); + let mut result_iter = result.iter(); + match_next!(result_iter, "text", var_style); + } + + #[test] + fn test_styled_variable_as_segments() { + const FORMAT_STR: &str = "[$var](red bold)"; + let var_style = Some(Color::Red.bold()); + let styled_style = Some(Color::Green.italic()); + let styled_no_modifier_style = Some(Color::Green.normal()); + + let formatter = StringFormatter::new(FORMAT_STR) + .unwrap() + .map_variables_to_segments(|variable| match variable { + "var" => Some(vec![ + _new_segment("_1".to_owned(), "styless".to_owned(), None), + _new_segment("_2".to_owned(), "styled".to_owned(), styled_style), + _new_segment( + "_3".to_owned(), + "styled_no_modifier".to_owned(), + styled_no_modifier_style, + ), + ]), + _ => None, + }); + let result = formatter.parse(None); + let mut result_iter = result.iter(); + match_next!(result_iter, "styless", var_style); + match_next!(result_iter, "styled", styled_style); + match_next!(result_iter, "styled_no_modifier", styled_no_modifier_style); + } + + #[test] fn test_parse_error() { // brackets without escape { diff --git a/src/segment.rs b/src/segment.rs index 73e24b9a8..13f527083 100644 --- a/src/segment.rs +++ b/src/segment.rs @@ -37,6 +37,11 @@ impl Segment { self } + /// Check if the segment has a style + pub fn has_style(&self) -> bool { + self.style.is_some() + } + /// Sets the value of the segment. pub fn set_value<T>(&mut self, value: T) -> &mut Self where |