diff --git a/base/src/formatter/format.rs b/base/src/formatter/format.rs index 55d8eb7..9076d33 100644 --- a/base/src/formatter/format.rs +++ b/base/src/formatter/format.rs @@ -245,6 +245,9 @@ pub fn format_number(value_original: f64, format: &str, locale: &Locale) -> Form } ParsePart::Number(p) => { let mut text = "".to_string(); + if let Some(c) = p.currency { + text = format!("{}", c); + } let tokens = &p.tokens; value = value * 100.0_f64.powi(p.percent) / (1000.0_f64.powi(p.comma)); // p.precision is the number of significant digits _after_ the decimal point diff --git a/base/src/formatter/lexer.rs b/base/src/formatter/lexer.rs index 094065d..014755c 100644 --- a/base/src/formatter/lexer.rs +++ b/base/src/formatter/lexer.rs @@ -10,6 +10,7 @@ pub struct Lexer { pub enum Token { Color(i32), // [Red] or [Color 23] Condition(Compare, f64), // [<=100] (Comparator, number) + Currency(char), // [$€] ($ currency symbol) Literal(char), // €, $, (, ), /, :, +, -, ^, ', {, }, <, =, !, ~, > and space or scaped \X Spacer(char), // *X Ghost(char), // _X @@ -274,6 +275,15 @@ impl Lexer { self.set_error("Failed to parse condition"); Token::ILLEGAL } + } else if c == '$' { + // currency + self.read_next_char(); + if let Some(currency) = self.read_next_char() { + self.read_next_char(); + return Token::Currency(currency); + } + self.set_error("Failed to parse currency"); + Token::ILLEGAL } else { // Color if let Some(index) = self.consume_color() { diff --git a/base/src/formatter/mod.rs b/base/src/formatter/mod.rs index e38cb1e..3f452af 100644 --- a/base/src/formatter/mod.rs +++ b/base/src/formatter/mod.rs @@ -74,6 +74,7 @@ mod test; // // * Color [Red] or [Color 23] or [Color23] // * Conditions [<100] +// * Currency [$€] // * Space _X when X is any given char // * A spacer of chars: *X where X is repeated as much as possible // * Literals: $, (, ), :, +, - and space diff --git a/base/src/formatter/parser.rs b/base/src/formatter/parser.rs index 1682492..9b44d94 100644 --- a/base/src/formatter/parser.rs +++ b/base/src/formatter/parser.rs @@ -40,6 +40,7 @@ pub struct NumberPart { pub is_scientific: bool, pub scientific_minus: bool, pub exponent_digit_count: i32, + pub currency: Option, } pub struct DatePart { @@ -114,6 +115,7 @@ impl Parser { let mut exponent_digit_count = 0; let mut number = 'i'; let mut index = 0; + let mut currency = None; while token != Token::EOF && token != Token::Separator { let next_token = self.lexer.next_token(); @@ -170,6 +172,9 @@ impl Parser { Token::Condition(cmp, value) => { condition = Some((cmp, value)); } + Token::Currency(c) => { + currency = Some(c); + } Token::QuestionMark => { tokens.push(TextToken::Digit(Digit { kind: '?', @@ -291,6 +296,7 @@ impl Parser { is_scientific, scientific_minus, exponent_digit_count, + currency, }) } } diff --git a/base/src/formatter/test/test_general.rs b/base/src/formatter/test/test_general.rs index cdebe36..771a5ad 100644 --- a/base/src/formatter/test/test_general.rs +++ b/base/src/formatter/test/test_general.rs @@ -76,6 +76,14 @@ fn test_color() { assert_eq!(format_number(3.1, "[blue]0.00", locale).color, Some(4)); } +#[test] +fn dollar_euro() { + let locale = get_default_locale(); + let format = "[$€]#,##0.00"; + let t = format_number(3.1, format, locale); + assert_eq!(t.text, "€3.10"); +} + #[test] fn test_parts() { let locale = get_default_locale();