From d02b7cd4c4720404e5f75bb601e569ee1bcfced9 Mon Sep 17 00:00:00 2001 From: Bryan Malyn Date: Fri, 3 Jan 2025 18:21:51 -0600 Subject: [PATCH] formatter[eng]: Reapply prefix after rounding Fixes: #2081 --- cspell.yaml | 9 ++--- src/formatting/formatter/eng.rs | 59 +++++++++++++++++++++++++++++++-- src/formatting/prefix.rs | 4 +++ 3 files changed, 65 insertions(+), 7 deletions(-) diff --git a/cspell.yaml b/cspell.yaml index 260e56e952..2307719d14 100644 --- a/cspell.yaml +++ b/cspell.yaml @@ -31,6 +31,7 @@ words: - bugz - busctl - caldav + - ccache - chrono - clippy - CLOEXEC @@ -167,6 +168,7 @@ words: - tzset - udev - uevent + - unapply - unshift - unspec - upower @@ -188,9 +190,8 @@ words: - xrandr - xtask - zbus - - zvariant - - zwlr - - zswap - zram + - zswap - Zswapped - - ccache + - zvariant + - zwlr diff --git a/src/formatting/formatter/eng.rs b/src/formatting/formatter/eng.rs index 1fb1f9a350..b8e3b070ef 100644 --- a/src/formatting/formatter/eng.rs +++ b/src/formatting/formatter/eng.rs @@ -139,7 +139,7 @@ impl Formatter for EngFormatter { (None, _) => (Prefix::min_available(), Prefix::max_available()), }; - let prefix = unit + let mut prefix = unit .clamp_prefix(if min_prefix.is_binary() { Prefix::eng_binary(val) } else { @@ -160,8 +160,27 @@ impl Formatter for EngFormatter { let sign = if is_negative { "-" } else { "" }; let mut retval = match self.width as i32 - digits { - i32::MIN..=0 => format!("{sign}{}", val.round()), - 1 => format!("{}{sign}{}", self.pad_with, val.round() as i64), + i32::MIN..=1 => { + // Remove prefix after rounding value to be displayed + val = prefix.unapply(val.round()); + + prefix = unit + .clamp_prefix(if min_prefix.is_binary() { + Prefix::eng_binary(val) + } else { + Prefix::eng(val) + }) + .clamp(min_prefix, max_prefix); + val = prefix.apply(val); + + digits = (val.max(1.).log10().floor() + 1.0) as i32 + is_negative as i32; + + match self.width as i32 - digits { + i32::MIN..=0 => format!("{sign}{}", val), + 1 => format!("{}{sign}{}", self.pad_with, val as i64), + rest => format!("{sign}{val:.*}", rest as usize - 1), + } + } rest => format!("{sign}{val:.*}", rest as usize - 1), }; @@ -278,6 +297,40 @@ mod tests { ) .unwrap(); assert_eq!(result, "321.6GB"); + + let fmt = new_fmt!(eng, w: 3, p: K).unwrap(); + let result = fmt + .format( + &Value::Number { + val: 998_888., + unit: Unit::Bytes, + }, + &config, + ) + .unwrap(); + assert_eq!(result, "999KB"); + + let result = fmt + .format( + &Value::Number { + val: 999_888., + unit: Unit::Bytes, + }, + &config, + ) + .unwrap(); + assert_eq!(result, "1.0MB"); + + let result = fmt + .format( + &Value::Number { + val: 1_000_000., + unit: Unit::Bytes, + }, + &config, + ) + .unwrap(); + assert_eq!(result, "1.0MB"); } #[test] diff --git a/src/formatting/prefix.rs b/src/formatting/prefix.rs index 30944cfb55..a7ce79c526 100644 --- a/src/formatting/prefix.rs +++ b/src/formatting/prefix.rs @@ -71,6 +71,10 @@ impl Prefix { value / MUL[self as usize] } + pub fn unapply(self, value: f64) -> f64 { + value * MUL[self as usize] + } + pub fn eng(mut number: f64) -> Self { if number == 0.0 { Self::One