Improve number display (#2936)

This commit is contained in:
Malo 2023-12-14 14:21:25 +01:00 committed by GitHub
parent 9024121905
commit 7adeb49652
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 51 additions and 20 deletions

View File

@ -51,7 +51,7 @@ impl f64 {
impl Repr for f64 { impl Repr for f64 {
fn repr(&self) -> EcoString { fn repr(&self) -> EcoString {
repr::format_float(*self, None, "") repr::format_float(*self, None, true, "")
} }
} }

View File

@ -53,7 +53,7 @@ impl i64 {
impl Repr for i64 { impl Repr for i64 {
fn repr(&self) -> EcoString { fn repr(&self) -> EcoString {
repr::format_int_with_base(*self, 10) eco_format!("{:?}", self)
} }
} }

View File

@ -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 /// Converts a float to a string representation with a specific precision and a
/// suffix, all with a single allocation. /// 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 { if let Some(p) = precision {
let offset = 10_f64.powi(p as i32); let offset = 10_f64.powi(p as i32);
value = (value * offset).round() / offset; value = (value * offset).round() / offset;
} }
// Debug for f64 always prints a decimal separator, while Display only does
// when necessary.
if value.is_nan() { if value.is_nan() {
"NaN".into() "NaN".into()
} else if value.is_sign_negative() { } else if force_separator {
eco_format!("{}{}{}", MINUS_SIGN, value.abs(), suffix) eco_format!("{:?}{}", value, suffix)
} else { } else {
eco_format!("{}{}", value, suffix) 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". /// Format pieces separated with commas and a final "and" or "or".
pub fn separated_list(pieces: &[impl AsRef<str>], last: &str) -> String { pub fn separated_list(pieces: &[impl AsRef<str>], last: &str) -> String {
let mut buf = String::new(); let mut buf = String::new();

View File

@ -762,7 +762,7 @@ pub enum ToStr {
cast! { cast! {
ToStr, ToStr,
v: i64 => Self::Int(v), 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: Version => Self::Str(format_str!("{}", v)),
v: Bytes => Self::Str( v: Bytes => Self::Str(
std::str::from_utf8(&v) std::str::from_utf8(&v)

View File

@ -202,7 +202,7 @@ impl Value {
match self { match self {
Self::None => Content::empty(), Self::None => Content::empty(),
Self::Int(v) => TextElem::packed(repr::format_int_with_base(v, 10)), 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::Str(v) => TextElem::packed(v),
Self::Version(v) => TextElem::packed(eco_format!("{v}")), Self::Version(v) => TextElem::packed(eco_format!("{v}")),
Self::Symbol(v) => TextElem::packed(v.get()), Self::Symbol(v) => TextElem::packed(v.get()),

View File

@ -148,7 +148,7 @@ impl Debug for Abs {
impl Repr for Abs { impl Repr for Abs {
fn repr(&self) -> EcoString { fn repr(&self) -> EcoString {
repr::format_float(self.to_pt(), Some(2), "pt") repr::format_float_with_unit(self.to_pt(), "pt")
} }
} }

View File

@ -135,7 +135,7 @@ impl Debug for Angle {
impl Repr for Angle { impl Repr for Angle {
fn repr(&self) -> EcoString { fn repr(&self) -> EcoString {
repr::format_float(self.to_deg(), Some(2), "deg") repr::format_float_with_unit(self.to_deg(), "deg")
} }
} }

View File

@ -85,7 +85,7 @@ impl Debug for Em {
impl Repr for Em { impl Repr for Em {
fn repr(&self) -> EcoString { fn repr(&self) -> EcoString {
repr::format_float(self.get(), None, "em") repr::format_float_with_unit(self.get(), "em")
} }
} }

View File

@ -79,7 +79,7 @@ impl Debug for Fr {
impl Repr for Fr { impl Repr for Fr {
fn repr(&self) -> EcoString { fn repr(&self) -> EcoString {
repr::format_float(self.get(), Some(2), "fr") repr::format_float_with_unit(self.get(), "fr")
} }
} }

View File

@ -76,7 +76,7 @@ impl Debug for Ratio {
impl Repr for Ratio { impl Repr for Ratio {
fn repr(&self) -> EcoString { fn repr(&self) -> EcoString {
repr::format_float(self.get() * 100.0, Some(2), "%") repr::format_float_with_unit(self.get() * 100.0, "%")
} }
} }

View File

@ -1472,15 +1472,15 @@ impl Repr for Color {
eco_format!( eco_format!(
"oklab({}, {}, {})", "oklab({}, {}, {})",
Ratio::new(c.l as _).repr(), Ratio::new(c.l as _).repr(),
repr::format_float(c.a as _, Some(3), ""), repr::format_float_component(c.a as _),
repr::format_float(c.b as _, Some(3), ""), repr::format_float_component(c.b as _),
) )
} else { } else {
eco_format!( eco_format!(
"oklab({}, {}, {}, {})", "oklab({}, {}, {}, {})",
Ratio::new(c.l as _).repr(), Ratio::new(c.l as _).repr(),
repr::format_float(c.a as _, Some(3), ""), repr::format_float_component(c.a as _),
repr::format_float(c.b as _, Some(3), ""), repr::format_float_component(c.b as _),
Ratio::new(c.alpha as _).repr(), Ratio::new(c.alpha as _).repr(),
) )
} }
@ -1490,14 +1490,14 @@ impl Repr for Color {
eco_format!( eco_format!(
"oklch({}, {}, {})", "oklch({}, {}, {})",
Ratio::new(c.l as _).repr(), 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(), hue_angle(c.hue.into_degrees()).repr(),
) )
} else { } else {
eco_format!( eco_format!(
"oklch({}, {}, {}, {})", "oklch({}, {}, {}, {})",
Ratio::new(c.l as _).repr(), 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(), hue_angle(c.hue.into_degrees()).repr(),
Ratio::new(c.alpha as _).repr(), Ratio::new(c.alpha as _).repr(),
) )

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 180 KiB

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -76,7 +76,7 @@
#test((5em + 6in).abs.inches(), 6.0) #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 // Hint: 2-21 use `length.abs.pt()` instead to ignore its em component
#(10.5em - 6pt).pt() #(10.5em - 6pt).pt()
@ -86,7 +86,7 @@
#(3em).cm() #(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 // Hint: 2-20 use `length.abs.mm()` instead to ignore its em component
#(93em - 80mm).mm() #(93em - 80mm).mm()