mirror of
https://github.com/uutils/coreutils.git
synced 2026-06-10 15:48:22 -07:00
du: honor LC_NUMERIC for decimal separator (#12357)
* du: honor LC_NUMERIC for decimal separator Route the fractional digit in `uucore::format::human::format_prefixed` through `locale_decimal_separator()`, the same helper #11941 added for `numfmt`. Fixes #11956. * du: spell-check: ignore `replacen` Matches the directive in `src/uu/numfmt/src/format.rs` for the same helper introduced by #11941.
This commit is contained in:
@@ -25,6 +25,7 @@ clap = { workspace = true }
|
||||
uucore = { workspace = true, features = [
|
||||
"format",
|
||||
"fsext",
|
||||
"i18n-decimal",
|
||||
"parser-size",
|
||||
"parser-glob",
|
||||
"time",
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
// spell-checker:ignore gnulibs sfmt
|
||||
// spell-checker:ignore gnulibs sfmt replacen
|
||||
|
||||
//! `human`-size formatting
|
||||
//!
|
||||
@@ -24,6 +24,7 @@ pub enum SizeFormat {
|
||||
/// 3. The human-readable format uses powers for 1024, but does not display the "i"
|
||||
/// that is commonly used to denote Kibi, Mebi, etc.
|
||||
/// 4. Kibi and Kilo are denoted differently ("k" and "K", respectively)
|
||||
/// 5. The decimal separator follows LC_NUMERIC ("1.3M" in C, "1,3M" in fr_FR)
|
||||
fn format_prefixed(prefixed: &NumberPrefix<f64>) -> String {
|
||||
match prefixed {
|
||||
NumberPrefix::Standalone(bytes) => bytes.to_string(),
|
||||
@@ -36,12 +37,29 @@ fn format_prefixed(prefixed: &NumberPrefix<f64>) -> String {
|
||||
if (10.0 * bytes).ceil() >= 100.0 {
|
||||
format!("{:.0}{prefix_str}", bytes.ceil())
|
||||
} else {
|
||||
format!("{:.1}{prefix_str}", (10.0 * bytes).ceil() / 10.0)
|
||||
let number = format!("{:.1}", (10.0 * bytes).ceil() / 10.0);
|
||||
format!("{}{prefix_str}", localize_decimal(number))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn localize_decimal(s: String) -> String {
|
||||
#[cfg(feature = "i18n-decimal")]
|
||||
{
|
||||
let sep = crate::i18n::decimal::locale_decimal_separator();
|
||||
if sep == "." {
|
||||
s
|
||||
} else {
|
||||
s.replacen('.', sep, 1)
|
||||
}
|
||||
}
|
||||
#[cfg(not(feature = "i18n-decimal"))]
|
||||
{
|
||||
s
|
||||
}
|
||||
}
|
||||
|
||||
pub fn human_readable(size: u64, sfmt: SizeFormat) -> String {
|
||||
match sfmt {
|
||||
SizeFormat::Binary => format_prefixed(&NumberPrefix::binary(size as f64)),
|
||||
|
||||
@@ -948,6 +948,26 @@ fn test_du_h_precision() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg_attr(wasi_runner, ignore = "WASI: locale env vars not propagated")]
|
||||
fn test_du_h_locale_decimal_separator() {
|
||||
for (locale, expected) in [("fr_FR.UTF-8", "8,4K"), ("C", "8.4K")] {
|
||||
let (at, mut ucmd) = at_and_ucmd!();
|
||||
|
||||
let fpath = at.plus("test.txt");
|
||||
std::fs::File::create(&fpath)
|
||||
.expect("cannot create test file")
|
||||
.set_len(8500)
|
||||
.expect("cannot truncate test len to size");
|
||||
ucmd.env("LC_ALL", locale)
|
||||
.arg("-h")
|
||||
.arg("--apparent-size")
|
||||
.arg(&fpath)
|
||||
.succeeds()
|
||||
.stdout_only(format!("{expected}\t{}\n", fpath.to_string_lossy()));
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_lines)]
|
||||
#[cfg(feature = "touch")]
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user