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 <noreply@anthropic.com>
This commit is contained in:
Brandon Thomas 2026-10-10 14:49:24 -04:00
parent 3e40014eb0
commit 5b15827ede
2 changed files with 17 additions and 2 deletions

View File

@ -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));
}

View File

@ -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::<f64>().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()))