From 3d744cc8a29f9e209795fb75dc7ed4cb5ea6dfce Mon Sep 17 00:00:00 2001 From: Steve Jason <145211128+56steve@users.noreply.github.com> Date: Fri, 30 Oct 2026 06:42:04 +0000 Subject: [PATCH] A formula that is a bare number gets the design unit (#9261) --- crates/doc/src/expr.rs | 8 ++++++-- crates/doc/src/params.rs | 13 +++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/crates/doc/src/expr.rs b/crates/doc/src/expr.rs index 9c8ca556d4..935698e9f4 100644 --- a/crates/doc/src/expr.rs +++ b/crates/doc/src/expr.rs @@ -589,9 +589,11 @@ pub fn is_literal(s: &str) -> bool { } } -/// Is the expression a bare number without a unit, like `20` or `-1.5`? +/// Is the expression a bare number without a unit, like `20` or `-1.5`? A leading `=` only marks +/// a formula (#4681), so `=20` is the same bare number. pub fn is_bare_number(s: &str) -> bool { - is_literal(s) && s.trim().trim_start_matches(['-', '+']).trim().parse::().is_ok() + let number = s.trim().strip_prefix('=').unwrap_or(s); + is_literal(s) && number.trim().trim_start_matches(['-', '+']).trim().parse::().is_ok() } /// Is `s` shaped like a parameter name: a letter or `_`, then letters, digits and `_`? The shape @@ -1449,6 +1451,8 @@ mod tests { assert!(is_literal("20") && is_literal("-1.5 in") && is_literal("3 deg")); assert!(!is_literal("d1") && !is_literal("2 * 3") && !is_literal("2 width")); assert!(is_bare_number(" -1.5 ") && is_bare_number("+2") && !is_bare_number("20 mm") && !is_bare_number("(2)")); + // A leading `=` only marks a formula (#4681): `=5` is the bare number `5`, not `==5`. + assert!(is_bare_number("=5") && is_bare_number(" = -1.5") && !is_bare_number("=5 mm") && !is_bare_number("==5") && !is_bare_number("=d3")); assert_eq!((length_unit_or_mm(" in "), length_unit_or_mm("deg"), length_unit_or_mm("")), ("in", "mm", "mm")); } diff --git a/crates/doc/src/params.rs b/crates/doc/src/params.rs index 87f601dcbe..78e6b2c869 100644 --- a/crates/doc/src/params.rs +++ b/crates/doc/src/params.rs @@ -1150,6 +1150,19 @@ mod design_length_tests { assert_eq!(written("", 5.0), w("mm", "5 mm")); } + /// A bare number typed as a formula (`=5`) means the design's units like `5` does. + #[test] + fn a_formula_that_is_a_bare_number_gets_the_design_unit() { + let mut doc = Document::new("Units"); + doc.units = "in".into(); + let length = crate::expr::Kind::Length; + assert_eq!(doc.with_design_unit("5", length), "5 in"); + assert_eq!(doc.with_design_unit("=5", length), "=5 in"); + assert_eq!(doc.with_design_unit("=5 mm", length), "=5 mm"); + let inches = doc.eval(&doc.with_design_unit("=5", length), length).unwrap(); + assert!((inches - 127.0).abs() < 1e-9, "{inches}"); + } + #[test] fn the_written_value_reads_back_within_a_micrometre() { for units in ["mm", "cm", "m", "in", "ft"] {