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"] {