From 5b15827edec4adc1101576da257ec7f4d949bb5d Mon Sep 17 00:00:00 2001 From: Brandon Thomas Date: Sat, 10 Oct 2026 14:49:24 -0400 Subject: [PATCH] Maintainer fix-up: leave English formula display untouched, match engine formula detection English (and languages without a formula table) now shows stored formula text verbatim instead of re-parsing it every frame; localized entry no longer trims leading spaces before formula detection (" =1" stays text, as in the engine). Adds a display round-trip test for string literals containing separators, decimal commas and the intersection operator. Co-Authored-By: Claude Opus 5.5 --- crates/formula/tests/spanish_input.rs | 9 +++++++++ crates/ui-egui/src/formula_locale.rs | 10 ++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/crates/formula/tests/spanish_input.rs b/crates/formula/tests/spanish_input.rs index e68de82..fee688a 100644 --- a/crates/formula/tests/spanish_input.rs +++ b/crates/formula/tests/spanish_input.rs @@ -89,3 +89,12 @@ fn locale_controls_decimal_list_array_separators_and_display() { assert_eq!(shown, "LET(SUMA;LAMBDA(x;x+1);SUM(SUMA(2);FALSE))"); assert_eq!(print(&parse_input(&shown, es, |n| n == "FALSO").unwrap()), print(&expr)); } + +#[test] +fn spanish_display_round_trips_text_containing_separators() { + let es = FormulaLocale::Es; + let expr = parse(r#"IF(A1="a,b;c",CONCAT("1.5",",",";"),SUM(0.25,A1:A3 B2))"#).unwrap(); + let shown = print_input(&expr, es, |_| false).unwrap(); + assert_eq!(shown, r#"SI(A1="a,b;c";CONCAT("1.5";",";";");SUMA(0,25;A1:A3 B2))"#); + assert_eq!(print(&parse_input(&shown, es, |_| false).unwrap()), print(&expr)); +} diff --git a/crates/ui-egui/src/formula_locale.rs b/crates/ui-egui/src/formula_locale.rs index a6d3d1b..ad0725e 100644 --- a/crates/ui-egui/src/formula_locale.rs +++ b/crates/ui-egui/src/formula_locale.rs @@ -12,7 +12,8 @@ pub(crate) fn canonical( if locale == FormulaLocale::En || wb.sheet(sheet).is_some_and(|sh| wb.styles.get(sh.style_id(cell)).num_fmt.as_str() == "@") { return Ok(text.to_string()); } - let body = text.trim(); + // Same formula detection as the engine's `input_to_cell` (no trimming: " =1" is text). + let body = text; if body.starts_with('=') || ((body.starts_with('+') || body.starts_with('-')) && body.chars().nth(1).is_some_and(|c| c.is_ascii_alphabetic() || c == '(')) { @@ -30,7 +31,7 @@ pub(crate) fn canonical( return Ok(format!("={}", formula::print(&expr?))); } // Decimal-comma number entry follows the same preference, without rewriting text or dates. - let normalized = body.replace(locale.decimal_separator(), "."); + let normalized = body.trim().replace(locale.decimal_separator(), "."); let number = normalized.strip_suffix('%').unwrap_or(&normalized); if number.parse::().is_ok_and(f64::is_finite) { return Ok(normalized); @@ -39,6 +40,11 @@ pub(crate) fn canonical( } pub(crate) fn display(text: &str, locale: FormulaLocale, wb: &Workbook, sheet: usize) -> String { + // English (and every language without a formula table) shows the stored text untouched, + // and skips a parse per frame. + if locale == FormulaLocale::En { + return text.to_string(); + } let Some(body) = text.strip_prefix('=') else { return text.to_string() }; formula::parse(body) .and_then(|expr| formula::print_input(&expr, locale, |name| wb.name(name, sheet).is_some() || wb.table(name).is_some()))