mirror of
https://github.com/uutils/coreutils
synced 2024-12-12 22:32:53 +00:00
ls,uucore: extract display human_readable()
helper from ls
This commit extract the `display_size()` helper from `ls` into `uucore` as `human_readable` to be similar to the gnulib helper so that the human readable display of sizes can be shared between ls, du, df.
This commit is contained in:
parent
eacf53d010
commit
d07fb73630
5 changed files with 68 additions and 39 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
@ -3325,6 +3325,7 @@ dependencies = [
|
|||
"md-5",
|
||||
"memchr",
|
||||
"nix",
|
||||
"number_prefix",
|
||||
"once_cell",
|
||||
"os_display",
|
||||
"sha1",
|
||||
|
|
|
@ -12,7 +12,6 @@ use clap::{
|
|||
use glob::{MatchOptions, Pattern};
|
||||
use lscolors::{LsColors, Style};
|
||||
|
||||
use number_prefix::NumberPrefix;
|
||||
use std::{cell::OnceCell, num::IntErrorKind};
|
||||
use std::{collections::HashSet, io::IsTerminal};
|
||||
|
||||
|
@ -37,6 +36,7 @@ use std::{
|
|||
use term_grid::{Cell, Direction, Filling, Grid, GridOptions};
|
||||
use unicode_width::UnicodeWidthStr;
|
||||
use uucore::error::USimpleError;
|
||||
use uucore::format::human::{human_readable, SizeFormat};
|
||||
#[cfg(all(unix, not(any(target_os = "android", target_os = "macos"))))]
|
||||
use uucore::fsxattr::has_acl;
|
||||
#[cfg(any(
|
||||
|
@ -313,13 +313,6 @@ enum Sort {
|
|||
Width,
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum SizeFormat {
|
||||
Bytes,
|
||||
Binary, // Powers of 1024, --human-readable, -h
|
||||
Decimal, // Powers of 1000, --si
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq)]
|
||||
enum Files {
|
||||
All,
|
||||
|
@ -3038,30 +3031,6 @@ fn display_date(metadata: &Metadata, config: &Config) -> String {
|
|||
}
|
||||
}
|
||||
|
||||
// There are a few peculiarities to how GNU formats the sizes:
|
||||
// 1. One decimal place is given if and only if the size is smaller than 10
|
||||
// 2. It rounds sizes up.
|
||||
// 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)
|
||||
fn format_prefixed(prefixed: &NumberPrefix<f64>) -> String {
|
||||
match prefixed {
|
||||
NumberPrefix::Standalone(bytes) => bytes.to_string(),
|
||||
NumberPrefix::Prefixed(prefix, bytes) => {
|
||||
// Remove the "i" from "Ki", "Mi", etc. if present
|
||||
let prefix_str = prefix.symbol().trim_end_matches('i');
|
||||
|
||||
// Check whether we get more than 10 if we round up to the first decimal
|
||||
// because we want do display 9.81 as "9.9", not as "10".
|
||||
if (10.0 * bytes).ceil() >= 100.0 {
|
||||
format!("{:.0}{}", bytes.ceil(), prefix_str)
|
||||
} else {
|
||||
format!("{:.1}{}", (10.0 * bytes).ceil() / 10.0, prefix_str)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
enum SizeOrDeviceId {
|
||||
Size(String),
|
||||
|
@ -3104,13 +3073,7 @@ fn display_len_or_rdev(metadata: &Metadata, config: &Config) -> SizeOrDeviceId {
|
|||
}
|
||||
|
||||
fn display_size(size: u64, config: &Config) -> String {
|
||||
// NOTE: The human-readable behavior deviates from the GNU ls.
|
||||
// The GNU ls uses binary prefixes by default.
|
||||
match config.size_format {
|
||||
SizeFormat::Binary => format_prefixed(&NumberPrefix::binary(size as f64)),
|
||||
SizeFormat::Decimal => format_prefixed(&NumberPrefix::decimal(size as f64)),
|
||||
SizeFormat::Bytes => size.to_string(),
|
||||
}
|
||||
human_readable(size, config.size_format)
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
|
|
|
@ -20,6 +20,7 @@ path = "src/lib/lib.rs"
|
|||
[dependencies]
|
||||
clap = { workspace = true }
|
||||
uucore_procs = { workspace = true }
|
||||
number_prefix = { workspace = true }
|
||||
dns-lookup = { version = "2.0.4", optional = true }
|
||||
dunce = { version = "1.0.4", optional = true }
|
||||
wild = "2.2"
|
||||
|
|
63
src/uucore/src/lib/features/format/human.rs
Normal file
63
src/uucore/src/lib/features/format/human.rs
Normal file
|
@ -0,0 +1,63 @@
|
|||
// This file is part of the uutils coreutils package.
|
||||
//
|
||||
// For the full copyright and license information, please view the LICENSE
|
||||
// file that was distributed with this source code.
|
||||
|
||||
//! `human`-size formating
|
||||
//!
|
||||
//! Format sizes like gnulibs human_readable() would
|
||||
|
||||
use number_prefix::NumberPrefix;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub enum SizeFormat {
|
||||
Bytes,
|
||||
Binary, // Powers of 1024, --human-readable, -h
|
||||
Decimal, // Powers of 1000, --si
|
||||
}
|
||||
|
||||
// There are a few peculiarities to how GNU formats the sizes:
|
||||
// 1. One decimal place is given if and only if the size is smaller than 10
|
||||
// 2. It rounds sizes up.
|
||||
// 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)
|
||||
fn format_prefixed(prefixed: &NumberPrefix<f64>) -> String {
|
||||
match prefixed {
|
||||
NumberPrefix::Standalone(bytes) => bytes.to_string(),
|
||||
NumberPrefix::Prefixed(prefix, bytes) => {
|
||||
// Remove the "i" from "Ki", "Mi", etc. if present
|
||||
let prefix_str = prefix.symbol().trim_end_matches('i');
|
||||
|
||||
// Check whether we get more than 10 if we round up to the first decimal
|
||||
// because we want do display 9.81 as "9.9", not as "10".
|
||||
if (10.0 * bytes).ceil() >= 100.0 {
|
||||
format!("{:.0}{}", bytes.ceil(), prefix_str)
|
||||
} else {
|
||||
format!("{:.1}{}", (10.0 * bytes).ceil() / 10.0, prefix_str)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn human_readable(size: u64, sfmt: SizeFormat) -> String {
|
||||
match sfmt {
|
||||
SizeFormat::Binary => format_prefixed(&NumberPrefix::binary(size as f64)),
|
||||
SizeFormat::Decimal => format_prefixed(&NumberPrefix::decimal(size as f64)),
|
||||
SizeFormat::Bytes => size.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[test]
|
||||
fn test_human_readable() {
|
||||
let test_cases = [
|
||||
(133456345, SizeFormat::Binary, "128M"),
|
||||
(12 * 1024 * 1024, SizeFormat::Binary, "12M"),
|
||||
(8500, SizeFormat::Binary, "8.4K"),
|
||||
];
|
||||
|
||||
for &(size, sfmt, expected_str) in &test_cases {
|
||||
assert_eq!(human_readable(size, sfmt), expected_str);
|
||||
}
|
||||
}
|
|
@ -32,6 +32,7 @@
|
|||
|
||||
mod argument;
|
||||
mod escape;
|
||||
pub mod human;
|
||||
pub mod num_format;
|
||||
pub mod num_parser;
|
||||
mod spec;
|
||||
|
|
Loading…
Reference in a new issue