Improve number display (#2936)
@ -51,7 +51,7 @@ impl f64 {
|
||||
|
||||
impl Repr for f64 {
|
||||
fn repr(&self) -> EcoString {
|
||||
repr::format_float(*self, None, "")
|
||||
repr::format_float(*self, None, true, "")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ impl i64 {
|
||||
|
||||
impl Repr for i64 {
|
||||
fn repr(&self) -> EcoString {
|
||||
repr::format_int_with_base(*self, 10)
|
||||
eco_format!("{:?}", self)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,20 +74,51 @@ pub fn format_int_with_base(mut n: i64, base: i64) -> EcoString {
|
||||
|
||||
/// Converts a float to a string representation with a specific precision and a
|
||||
/// suffix, all with a single allocation.
|
||||
pub fn format_float(mut value: f64, precision: Option<u8>, suffix: &str) -> EcoString {
|
||||
pub fn format_float(
|
||||
mut value: f64,
|
||||
precision: Option<u8>,
|
||||
force_separator: bool,
|
||||
suffix: &str,
|
||||
) -> EcoString {
|
||||
if let Some(p) = precision {
|
||||
let offset = 10_f64.powi(p as i32);
|
||||
value = (value * offset).round() / offset;
|
||||
}
|
||||
// Debug for f64 always prints a decimal separator, while Display only does
|
||||
// when necessary.
|
||||
if value.is_nan() {
|
||||
"NaN".into()
|
||||
} else if value.is_sign_negative() {
|
||||
eco_format!("{}{}{}", MINUS_SIGN, value.abs(), suffix)
|
||||
} else if force_separator {
|
||||
eco_format!("{:?}{}", value, suffix)
|
||||
} else {
|
||||
eco_format!("{}{}", value, suffix)
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a float to a string representation with a precision of three
|
||||
/// decimal places. This is intended to be used as part of a larger structure
|
||||
/// containing multiple float components, such as colors.
|
||||
pub fn format_float_component(value: f64) -> EcoString {
|
||||
format_float(value, Some(3), false, "")
|
||||
}
|
||||
|
||||
/// Converts a float to a string representation with a precision of two decimal
|
||||
/// places, followed by a unit.
|
||||
pub fn format_float_with_unit(value: f64, unit: &str) -> EcoString {
|
||||
format_float(value, Some(2), false, unit)
|
||||
}
|
||||
|
||||
/// Converts a float to a string that can be used to display the float as text.
|
||||
pub fn display_float(value: f64) -> EcoString {
|
||||
if value.is_nan() {
|
||||
"NaN".into()
|
||||
} else if value < 0.0 {
|
||||
eco_format!("{}{}", MINUS_SIGN, value.abs())
|
||||
} else {
|
||||
eco_format!("{}", value.abs())
|
||||
}
|
||||
}
|
||||
|
||||
/// Format pieces separated with commas and a final "and" or "or".
|
||||
pub fn separated_list(pieces: &[impl AsRef<str>], last: &str) -> String {
|
||||
let mut buf = String::new();
|
||||
|
@ -762,7 +762,7 @@ pub enum ToStr {
|
||||
cast! {
|
||||
ToStr,
|
||||
v: i64 => Self::Int(v),
|
||||
v: f64 => Self::Str(repr::format_float(v, None, "").into()),
|
||||
v: f64 => Self::Str(repr::display_float(v).into()),
|
||||
v: Version => Self::Str(format_str!("{}", v)),
|
||||
v: Bytes => Self::Str(
|
||||
std::str::from_utf8(&v)
|
||||
|
@ -202,7 +202,7 @@ impl Value {
|
||||
match self {
|
||||
Self::None => Content::empty(),
|
||||
Self::Int(v) => TextElem::packed(repr::format_int_with_base(v, 10)),
|
||||
Self::Float(v) => TextElem::packed(repr::format_float(v, None, "")),
|
||||
Self::Float(v) => TextElem::packed(repr::display_float(v)),
|
||||
Self::Str(v) => TextElem::packed(v),
|
||||
Self::Version(v) => TextElem::packed(eco_format!("{v}")),
|
||||
Self::Symbol(v) => TextElem::packed(v.get()),
|
||||
|
@ -148,7 +148,7 @@ impl Debug for Abs {
|
||||
|
||||
impl Repr for Abs {
|
||||
fn repr(&self) -> EcoString {
|
||||
repr::format_float(self.to_pt(), Some(2), "pt")
|
||||
repr::format_float_with_unit(self.to_pt(), "pt")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,7 @@ impl Debug for Angle {
|
||||
|
||||
impl Repr for Angle {
|
||||
fn repr(&self) -> EcoString {
|
||||
repr::format_float(self.to_deg(), Some(2), "deg")
|
||||
repr::format_float_with_unit(self.to_deg(), "deg")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ impl Debug for Em {
|
||||
|
||||
impl Repr for Em {
|
||||
fn repr(&self) -> EcoString {
|
||||
repr::format_float(self.get(), None, "em")
|
||||
repr::format_float_with_unit(self.get(), "em")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,7 @@ impl Debug for Fr {
|
||||
|
||||
impl Repr for Fr {
|
||||
fn repr(&self) -> EcoString {
|
||||
repr::format_float(self.get(), Some(2), "fr")
|
||||
repr::format_float_with_unit(self.get(), "fr")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -76,7 +76,7 @@ impl Debug for Ratio {
|
||||
|
||||
impl Repr for Ratio {
|
||||
fn repr(&self) -> EcoString {
|
||||
repr::format_float(self.get() * 100.0, Some(2), "%")
|
||||
repr::format_float_with_unit(self.get() * 100.0, "%")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1472,15 +1472,15 @@ impl Repr for Color {
|
||||
eco_format!(
|
||||
"oklab({}, {}, {})",
|
||||
Ratio::new(c.l as _).repr(),
|
||||
repr::format_float(c.a as _, Some(3), ""),
|
||||
repr::format_float(c.b as _, Some(3), ""),
|
||||
repr::format_float_component(c.a as _),
|
||||
repr::format_float_component(c.b as _),
|
||||
)
|
||||
} else {
|
||||
eco_format!(
|
||||
"oklab({}, {}, {}, {})",
|
||||
Ratio::new(c.l as _).repr(),
|
||||
repr::format_float(c.a as _, Some(3), ""),
|
||||
repr::format_float(c.b as _, Some(3), ""),
|
||||
repr::format_float_component(c.a as _),
|
||||
repr::format_float_component(c.b as _),
|
||||
Ratio::new(c.alpha as _).repr(),
|
||||
)
|
||||
}
|
||||
@ -1490,14 +1490,14 @@ impl Repr for Color {
|
||||
eco_format!(
|
||||
"oklch({}, {}, {})",
|
||||
Ratio::new(c.l as _).repr(),
|
||||
repr::format_float(c.chroma as _, Some(3), ""),
|
||||
repr::format_float_component(c.chroma as _),
|
||||
hue_angle(c.hue.into_degrees()).repr(),
|
||||
)
|
||||
} else {
|
||||
eco_format!(
|
||||
"oklch({}, {}, {}, {})",
|
||||
Ratio::new(c.l as _).repr(),
|
||||
repr::format_float(c.chroma as _, Some(3), ""),
|
||||
repr::format_float_component(c.chroma as _),
|
||||
hue_angle(c.hue.into_degrees()).repr(),
|
||||
Ratio::new(c.alpha as _).repr(),
|
||||
)
|
||||
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 8.1 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 49 KiB |
Before Width: | Height: | Size: 57 KiB After Width: | Height: | Size: 22 KiB |
Before Width: | Height: | Size: 180 KiB After Width: | Height: | Size: 37 KiB |
@ -76,7 +76,7 @@
|
||||
#test((5em + 6in).abs.inches(), 6.0)
|
||||
|
||||
---
|
||||
// Error: 2-21 cannot convert a length with non-zero em units (`−6pt + 10.5em`) to pt
|
||||
// Error: 2-21 cannot convert a length with non-zero em units (`-6pt + 10.5em`) to pt
|
||||
// Hint: 2-21 use `length.abs.pt()` instead to ignore its em component
|
||||
#(10.5em - 6pt).pt()
|
||||
|
||||
@ -86,7 +86,7 @@
|
||||
#(3em).cm()
|
||||
|
||||
---
|
||||
// Error: 2-20 cannot convert a length with non-zero em units (`−226.77pt + 93em`) to mm
|
||||
// Error: 2-20 cannot convert a length with non-zero em units (`-226.77pt + 93em`) to mm
|
||||
// Hint: 2-20 use `length.abs.mm()` instead to ignore its em component
|
||||
#(93em - 80mm).mm()
|
||||
|
||||
|