From 6589f77743a3ce94a288838e31c19fe63df4a83b Mon Sep 17 00:00:00 2001 From: Arkadiusz Bielewicz Date: Wed, 13 Oct 2021 10:47:38 +0200 Subject: [PATCH 1/9] #532 Improve date format validation to include all supported cases | Validation extended to support mentioned case. --- src/app.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/app.rs b/src/app.rs index f9781b5b0..fb41b43b5 100644 --- a/src/app.rs +++ b/src/app.rs @@ -304,6 +304,21 @@ pub fn validate_time_format(formatter: &str) -> Result<(), String> { | Some('U') | Some('u') | Some('V') | Some('v') | Some('W') | Some('w') | Some('X') | Some('x') | Some('Y') | Some('y') | Some('Z') | Some('z') | Some('+') | Some('%') => (), + Some(n @ '3') | Some(n @ '6') | Some(n @ '9') => match chars.next() { + Some('f') => (), + Some(c) => return Err(format!("invalid format specifier: %{}{}", n, c)), + None => return Err("missing format specifier".to_owned()), + } + Some('.') => match chars.next() { + Some('f') => (), + Some(n @ '3') | Some(n @ '6') | Some(n @ '9') => match chars.next() { + Some('f') => (), + Some(c) => return Err(format!("invalid format specifier: %.{}{}", n, c)), + None => return Err("missing format specifier".to_owned()), + } + Some(c) => return Err(format!("invalid format specifier: %.{}", c)), + None => return Err("missing format specifier".to_owned()), + } Some(c) => return Err(format!("invalid format specifier: %{}", c)), None => return Err("missing format specifier".to_owned()), }, From eb0487d5ef5c9104584f649ecdbc5a913d05a96a Mon Sep 17 00:00:00 2001 From: Arkadiusz Bielewicz Date: Wed, 13 Oct 2021 11:35:58 +0200 Subject: [PATCH 2/9] #532 Improve date format validation to include all supported cases | Formatting, test added --- src/app.rs | 6 +++--- tests/integration.rs | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/app.rs b/src/app.rs index fb41b43b5..90cd6997a 100644 --- a/src/app.rs +++ b/src/app.rs @@ -308,17 +308,17 @@ pub fn validate_time_format(formatter: &str) -> Result<(), String> { Some('f') => (), Some(c) => return Err(format!("invalid format specifier: %{}{}", n, c)), None => return Err("missing format specifier".to_owned()), - } + }, Some('.') => match chars.next() { Some('f') => (), Some(n @ '3') | Some(n @ '6') | Some(n @ '9') => match chars.next() { Some('f') => (), Some(c) => return Err(format!("invalid format specifier: %.{}{}", n, c)), None => return Err("missing format specifier".to_owned()), - } + }, Some(c) => return Err(format!("invalid format specifier: %.{}", c)), None => return Err("missing format specifier".to_owned()), - } + }, Some(c) => return Err(format!("invalid format specifier: %{}", c)), None => return Err("missing format specifier".to_owned()), }, diff --git a/tests/integration.rs b/tests/integration.rs index dfadeb725..8eddc78fb 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -592,3 +592,19 @@ fn test_custom_config_file_parsing() { .assert() .stdout(predicate::str::is_match("folder\nā””ā”€ā”€ file").unwrap()); } + +#[test] +fn test_date_custom_format_supports_nanos_with_length() { + let dir = tempdir(); + dir.child("one").touch().unwrap(); + dir.child("two").touch().unwrap(); + + cmd() + .arg("-l") + .arg("--date") + .arg("+testDateFormat%.3f") + .arg("--ignore-config") + .arg(dir.path()) + .assert() + .stdout(predicate::str::is_match("testDateFormat\\.[0-9]{3}").unwrap().count(2)); +} From 9a038deaa57622243b9c0f0a41156bbad0878571 Mon Sep 17 00:00:00 2001 From: Arkadiusz Bielewicz Date: Wed, 13 Oct 2021 11:41:03 +0200 Subject: [PATCH 3/9] #532 Improve date format validation to include all supported cases | CHANGELOG updated --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 08e19c2d2..4e93b9c3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add `--config-file` flag to read configuration file from a custom location - Clarify custom date format for `date` field in configuration file in the README. ### Fixed +- Specific length date formatting for nanos `.3/6/9f` fixed [#532](https://github.com/Peltoche/lsd/issues/532) ## [0.20.1] - 2021-03-07 ### Fixed From 35b956b06b46d0902f649829726ed28050936079 Mon Sep 17 00:00:00 2001 From: Arkadiusz Bielewicz Date: Wed, 13 Oct 2021 13:13:32 +0200 Subject: [PATCH 4/9] #532 Improve date format validation to include all supported cases | Added missing valid cases --- src/app.rs | 37 +++++++++++++++++++++++++------------ tests/integration.rs | 16 ++++++++++++++++ 2 files changed, 41 insertions(+), 12 deletions(-) diff --git a/src/app.rs b/src/app.rs index 90cd6997a..9850b69fc 100644 --- a/src/app.rs +++ b/src/app.rs @@ -246,8 +246,8 @@ pub fn build() -> App<'static, 'static> { ) .arg( Arg::with_name("classic") - .long("classic") - .help("Enable classic mode (display output similar to ls)"), + .long("classic") + .help("Enable classic mode (display output similar to ls)"), ) .arg( Arg::with_name("no-symlink") @@ -296,6 +296,29 @@ pub fn validate_time_format(formatter: &str) -> Result<(), String> { loop { match chars.next() { Some('%') => match chars.next() { + Some('.') => match chars.next() { + Some('f') => (), + Some(n @ '3') | Some(n @ '6') | Some(n @ '9') => match chars.next() { + Some('f') => (), + Some(c) => return Err(format!("invalid format specifier: %.{}{}", n, c)), + None => return Err("missing format specifier".to_owned()), + }, + Some(c) => return Err(format!("invalid format specifier: %.{}", c)), + None => return Err("missing format specifier".to_owned()), + }, + Some(n @ ':') | Some(n @ '#') => match chars.next() { + Some('z') => (), + Some(c) => return Err(format!("invalid format specifier: %{}{}", n, c)), + None => return Err("missing format specifier".to_owned()), + }, + Some(n @ '-') | Some(n @ '_') | Some(n @ '0') => match chars.next() { + Some('C') | Some('d') | Some('e') | Some('f') | Some('G') | Some('g') + | Some('H') | Some('I') | Some('j') | Some('k') | Some('l') | Some('M') + | Some('m') | Some('S') | Some('s') | Some('U') | Some('u') | Some('V') + | Some('W') | Some('w') | Some('Y') | Some('y') => (), + Some(c) => return Err(format!("invalid format specifier: %{}{}", n, c)), + None => return Err("missing format specifier".to_owned()), + } Some('A') | Some('a') | Some('B') | Some('b') | Some('C') | Some('c') | Some('D') | Some('d') | Some('e') | Some('F') | Some('f') | Some('G') | Some('g') | Some('H') | Some('h') | Some('I') | Some('j') | Some('k') @@ -309,16 +332,6 @@ pub fn validate_time_format(formatter: &str) -> Result<(), String> { Some(c) => return Err(format!("invalid format specifier: %{}{}", n, c)), None => return Err("missing format specifier".to_owned()), }, - Some('.') => match chars.next() { - Some('f') => (), - Some(n @ '3') | Some(n @ '6') | Some(n @ '9') => match chars.next() { - Some('f') => (), - Some(c) => return Err(format!("invalid format specifier: %.{}{}", n, c)), - None => return Err("missing format specifier".to_owned()), - }, - Some(c) => return Err(format!("invalid format specifier: %.{}", c)), - None => return Err("missing format specifier".to_owned()), - }, Some(c) => return Err(format!("invalid format specifier: %{}", c)), None => return Err("missing format specifier".to_owned()), }, diff --git a/tests/integration.rs b/tests/integration.rs index 8eddc78fb..b3f807308 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -608,3 +608,19 @@ fn test_date_custom_format_supports_nanos_with_length() { .assert() .stdout(predicate::str::is_match("testDateFormat\\.[0-9]{3}").unwrap().count(2)); } + +#[test] +fn test_date_custom_format_supports_padding() { + let dir = tempdir(); + dir.child("one").touch().unwrap(); + dir.child("two").touch().unwrap(); + + cmd() + .arg("-l") + .arg("--date") + .arg("+testDateFormat%_d") + .arg("--ignore-config") + .arg(dir.path()) + .assert() + .stdout(predicate::str::is_match("testDateFormat[\\s0-9]{2}").unwrap().count(2)); +} From 3667b75ab389c31d816147ba7a7ac890fab0f13f Mon Sep 17 00:00:00 2001 From: Arkadiusz Bielewicz Date: Wed, 13 Oct 2021 13:44:21 +0200 Subject: [PATCH 5/9] #532 Improve date format validation to include all supported cases | Adjusted CHANGELOG --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e93b9c3e..91f134778 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,7 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add `--config-file` flag to read configuration file from a custom location - Clarify custom date format for `date` field in configuration file in the README. ### Fixed -- Specific length date formatting for nanos `.3/6/9f` fixed [#532](https://github.com/Peltoche/lsd/issues/532) +- Support all `strftime` like formatting [#532](https://github.com/Peltoche/lsd/issues/532) ## [0.20.1] - 2021-03-07 ### Fixed From a1a5977ab85928391dc80476649f2863a6147392 Mon Sep 17 00:00:00 2001 From: Arkadiusz Bielewicz Date: Wed, 13 Oct 2021 13:45:55 +0200 Subject: [PATCH 6/9] #532 Improve date format validation to include all supported cases | fmt applied --- src/app.rs | 2 +- tests/integration.rs | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/app.rs b/src/app.rs index 9850b69fc..86bdf474a 100644 --- a/src/app.rs +++ b/src/app.rs @@ -318,7 +318,7 @@ pub fn validate_time_format(formatter: &str) -> Result<(), String> { | Some('W') | Some('w') | Some('Y') | Some('y') => (), Some(c) => return Err(format!("invalid format specifier: %{}{}", n, c)), None => return Err("missing format specifier".to_owned()), - } + }, Some('A') | Some('a') | Some('B') | Some('b') | Some('C') | Some('c') | Some('D') | Some('d') | Some('e') | Some('F') | Some('f') | Some('G') | Some('g') | Some('H') | Some('h') | Some('I') | Some('j') | Some('k') diff --git a/tests/integration.rs b/tests/integration.rs index b3f807308..574768a27 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -606,7 +606,11 @@ fn test_date_custom_format_supports_nanos_with_length() { .arg("--ignore-config") .arg(dir.path()) .assert() - .stdout(predicate::str::is_match("testDateFormat\\.[0-9]{3}").unwrap().count(2)); + .stdout( + predicate::str::is_match("testDateFormat\\.[0-9]{3}") + .unwrap() + .count(2), + ); } #[test] @@ -622,5 +626,9 @@ fn test_date_custom_format_supports_padding() { .arg("--ignore-config") .arg(dir.path()) .assert() - .stdout(predicate::str::is_match("testDateFormat[\\s0-9]{2}").unwrap().count(2)); + .stdout( + predicate::str::is_match("testDateFormat[\\s0-9]{2}") + .unwrap() + .count(2), + ); } From 932d7eb97bdb77f20ff5f6fd16bfe5988b10b223 Mon Sep 17 00:00:00 2001 From: Arkadiusz Bielewicz Date: Fri, 15 Oct 2021 13:58:21 +0200 Subject: [PATCH 7/9] #533 thousands separator for the --size=bytes option would be very useful | Added support for thousand separated bytes --- CHANGELOG.md | 1 + Cargo.lock | 34 ++++++++++++++++++++++++++++++++++ Cargo.toml | 1 + src/app.rs | 1 + src/flags/size.rs | 15 ++++++++++++++- src/meta/size.rs | 32 +++++++++++++++++++++++++++++--- 6 files changed, 80 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 91f134778..1a3aa9af6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add support for theme from [zwpaper](https://github.com/zwpaper) [#452](https://github.com/Peltoche/lsd/pull/452) - Update minimal rust version to 1.42.0 from [zwpaper](https://github.com/zwpaper) [#534](https://github.com/Peltoche/lsd/issues/534) - [`NO_COLOR`](https://no-color.org/) environment variable support from [AnInternetTroll](https://github.com/aninternettroll) +- Added `--size bytes-with-separator` flag to print bytes with thousands separated by `,` [#533](https://github.com/Peltoche/lsd/issues/533) ### Changed - Change size to use btyes in classic mode from [meain](https://github.com/meain) - Show tree edge before name block or first column if no name block from [zwpaper](https://github.com/zwpaper) [#468](https://github.com/Peltoche/lsd/issues/468) diff --git a/Cargo.lock b/Cargo.lock index 60204a7fb..509b6e074 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,7 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. +version = 3 + [[package]] name = "aho-corasick" version = "0.7.18" @@ -27,6 +29,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "arrayvec" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9fd44efafa8690358b7408d253adf110036b88f55672a933f01d616ad9b1b9" +dependencies = [ + "nodrop", +] + [[package]] name = "assert_cmd" version = "1.0.8" @@ -342,6 +353,12 @@ dependencies = [ "either", ] +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + [[package]] name = "lazy_static" version = "1.4.0" @@ -403,6 +420,7 @@ dependencies = [ "human-sort", "libc", "lscolors", + "num-format", "predicates 1.0.8", "serde", "serde_yaml", @@ -447,6 +465,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + [[package]] name = "normalize-line-endings" version = "0.3.0" @@ -462,6 +486,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "num-format" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465" +dependencies = [ + "arrayvec", + "itoa", +] + [[package]] name = "num-integer" version = "0.1.44" diff --git a/Cargo.toml b/Cargo.toml index 62b3a0aa9..4d0207956 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ xdg = "2.1.*" yaml-rust = "0.4.*" serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.8" +num-format = "0.4.0" [target.'cfg(unix)'.dependencies] users = "0.11.*" diff --git a/src/app.rs b/src/app.rs index 86bdf474a..575c08c08 100644 --- a/src/app.rs +++ b/src/app.rs @@ -131,6 +131,7 @@ pub fn build() -> App<'static, 'static> { .possible_value("default") .possible_value("short") .possible_value("bytes") + .possible_value("bytes-with-separator") .default_value("default") .multiple(true) .number_of_values(1) diff --git a/src/flags/size.rs b/src/flags/size.rs index 9f40d6a5d..bda6f4431 100644 --- a/src/flags/size.rs +++ b/src/flags/size.rs @@ -18,6 +18,8 @@ pub enum SizeFlag { Short, /// The variant to show file size in bytes. Bytes, + /// The variant to show file size in bytes with thousand separated by delimiter. + BytesWithSeparator, } impl SizeFlag { @@ -26,9 +28,10 @@ impl SizeFlag { "default" => Some(Self::Default), "short" => Some(Self::Short), "bytes" => Some(Self::Bytes), + "bytes-with-separator" => Some(Self::BytesWithSeparator), _ => { panic!( - "Size can only be one of default, short or bytes, but got {}.", + "Size can only be one of default, short, bytes or bytes-with-separator, but got {}.", value ); } @@ -170,4 +173,14 @@ mod test { c.classic = Some(true); assert_eq!(Some(SizeFlag::Bytes), SizeFlag::from_config(&c)); } + + #[test] + fn test_from_arg_matches_size_bytes_with_separators() { + let args = vec!["lsd", "--size", "bytes-with-separator"]; + let matches = app::build().get_matches_from_safe(args).unwrap(); + assert_eq!( + Some(SizeFlag::BytesWithSeparator), + SizeFlag::from_arg_matches(&matches) + ); + } } diff --git a/src/meta/size.rs b/src/meta/size.rs index 5a16bd4dc..9e9831335 100644 --- a/src/meta/size.rs +++ b/src/meta/size.rs @@ -1,5 +1,6 @@ use crate::color::{ColoredString, Colors, Elem}; use crate::flags::{Flags, SizeFlag}; +use num_format::{Locale, ToFormattedString}; use std::fs::Metadata; use std::iter::repeat; @@ -38,8 +39,19 @@ impl Size { format!("{0:.1$}", number, if number < 10.0 { 1 } else { 0 }) } + fn format_bytes(&self, flags: &Flags) -> String { + if flags.size == SizeFlag::BytesWithSeparator { + self.bytes.to_formatted_string(&Locale::en) + } else { + self.bytes.to_string() + } + } + pub fn get_unit(&self, flags: &Flags) -> Unit { - if self.bytes < 1024 || flags.size == SizeFlag::Bytes { + if self.bytes < 1024 + || flags.size == SizeFlag::Bytes + || flags.size == SizeFlag::BytesWithSeparator + { Unit::Byte } else if self.bytes < 1024 * 1024 { Unit::Kilo @@ -111,7 +123,7 @@ impl Size { match unit { Unit::None => "".to_string(), - Unit::Byte => self.bytes.to_string(), + Unit::Byte => self.format_bytes(flags), Unit::Kilo => self.format_size(((self.bytes as f64) / 1024.0 * 10.0).round() / 10.0), Unit::Mega => { self.format_size(((self.bytes as f64) / (1024.0 * 1024.0) * 10.0).round() / 10.0) @@ -151,7 +163,7 @@ impl Size { Unit::Giga => String::from("G"), Unit::Tera => String::from("T"), }, - SizeFlag::Bytes => String::from(""), + SizeFlag::Bytes | SizeFlag::BytesWithSeparator => String::from(""), } } } @@ -336,4 +348,18 @@ mod test { assert_eq!(size.render(&colors, &flags, Some(2)).to_string(), "42K"); assert_eq!(size.render(&colors, &flags, Some(3)).to_string(), " 42K"); } + + #[test] + fn render_bytes_with_separator() { + let size = Size::new(42 * 1024 * 1024); // == 42 megabytes + let mut flags = Flags::default(); + + flags.size = SizeFlag::Bytes; + assert_eq!(size.value_string(&flags).as_str(), "44040192"); + assert_eq!(size.unit_string(&flags).as_str(), ""); + + flags.size = SizeFlag::BytesWithSeparator; + assert_eq!(size.value_string(&flags).as_str(), "44,040,192"); + assert_eq!(size.unit_string(&flags).as_str(), ""); + } } From 7ec07b6168328c7ad51cfdb2ee1b1a5325a50ee4 Mon Sep 17 00:00:00 2001 From: Arkadiusz Bielewicz Date: Thu, 4 Nov 2021 11:40:47 +0100 Subject: [PATCH 8/9] #533 thousands separator for the --size=bytes option would be very useful | Use system setting to determine formatting - only on unix --- Cargo.lock | 331 ++++++++++++++++++++++++++++++++++++++++++++--- Cargo.toml | 3 +- src/meta/size.rs | 36 +++++- 3 files changed, 348 insertions(+), 22 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 509b6e074..d76667857 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,6 +2,21 @@ # It is not intended for manual editing. version = 3 +[[package]] +name = "addr2line" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ecd88a8c8378ca913a680cd98f0f13ac67383d35993f86c90a70e3f137816b" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + [[package]] name = "aho-corasick" version = "0.7.18" @@ -83,6 +98,44 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "backtrace" +version = "0.3.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "321629d8ba6513061f26707241fa9bc89524ff1cd7a915a97ef0c62c666ce1b6" +dependencies = [ + "addr2line", + "cc", + "cfg-if 1.0.0", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bindgen" +version = "0.47.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a817f8356b784c37ee29b7a9a15c3fec321cd46b0ec67bcebe5530207f62e2d" +dependencies = [ + "bitflags", + "cexpr", + "cfg-if 0.1.10", + "clang-sys", + "clap", + "env_logger", + "hashbrown 0.1.8", + "lazy_static", + "log", + "peeking_take_while", + "proc-macro2 0.4.30", + "quote 0.6.13", + "regex", + "shlex", + "which", +] + [[package]] name = "bitflags" version = "1.2.1" @@ -100,6 +153,33 @@ dependencies = [ "regex-automata", ] +[[package]] +name = "byteorder" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" + +[[package]] +name = "cc" +version = "1.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "79c2681d6594606957bbb8631c4b90a7fcaaa72cdb714743a437b156d6a7eedd" + +[[package]] +name = "cexpr" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fce5b5fb86b0c57c20c834c1b412fd09c77c8a59b9473f86272709e78874cd1d" +dependencies = [ + "nom", +] + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + [[package]] name = "cfg-if" version = "1.0.0" @@ -128,6 +208,17 @@ dependencies = [ "chrono", ] +[[package]] +name = "clang-sys" +version = "0.26.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ef0c1bcf2e99c649104bd7a7012d8f8802684400e03db0ec0af48583c6fa0e4" +dependencies = [ + "glob 0.2.11", + "libc", + "libloading", +] + [[package]] name = "clap" version = "2.33.3" @@ -150,7 +241,7 @@ version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d82cfc11ce7f2c3faef78d8a684447b40d503d9681acebed6cb728d45940c4db" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "lazy_static", ] @@ -230,6 +321,37 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "encoding_rs" +version = "0.8.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "env_logger" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aafcde04e90a5226a6443b7aabdb016ba2f8307c847d524724bd9b346dd1a2d3" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] + +[[package]] +name = "failure" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d32e9bd16cc02eae7db7ef620b392808b89f6a5e16bb3497d159c6b92a0f4f86" +dependencies = [ + "backtrace", +] + [[package]] name = "float-cmp" version = "0.8.0" @@ -251,11 +373,23 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "wasi", ] +[[package]] +name = "gimli" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78cc372d058dcf6d5ecd98510e7fbc9e5aec4d21de70f65fea8fecebcd881bd4" + +[[package]] +name = "glob" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8be18de09a56b60ed0edf84bc9df007e30040691af7acd1c41874faac5895bfb" + [[package]] name = "glob" version = "0.3.0" @@ -286,6 +420,16 @@ dependencies = [ "walkdir", ] +[[package]] +name = "hashbrown" +version = "0.1.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3bae29b6653b3412c2e71e9d486db9f9df5d701941d86683005efb9f2d28e3da" +dependencies = [ + "byteorder", + "scopeguard 0.3.3", +] + [[package]] name = "hashbrown" version = "0.11.2" @@ -307,6 +451,15 @@ version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "140a09c9305e6d5e557e2ed7cbc68e05765a7d4213975b87cb04920689cc6219" +[[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + [[package]] name = "ignore" version = "0.4.18" @@ -332,7 +485,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" dependencies = [ "autocfg", - "hashbrown", + "hashbrown 0.11.2", ] [[package]] @@ -341,7 +494,7 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bee0328b1209d157ef001c94dd85b4f8f64139adb0eac2659f4b08382b2f474d" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -371,6 +524,16 @@ version = "0.2.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a1fa8cddc8fbbee11227ef194b5317ed014b8acbf15139bd716a18ad3fe99ec5" +[[package]] +name = "libloading" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2b111a074963af1d37a139918ac6d49ad1d0d5e47f72fd55388619691a7d753" +dependencies = [ + "cc", + "winapi", +] + [[package]] name = "linked-hash-map" version = "0.5.4" @@ -383,7 +546,7 @@ version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb" dependencies = [ - "scopeguard", + "scopeguard 1.1.0", ] [[package]] @@ -392,7 +555,7 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", ] [[package]] @@ -430,7 +593,7 @@ dependencies = [ "terminal_size", "unicode-width", "users", - "version_check", + "version_check 0.9.3", "wild", "winapi", "xdg", @@ -443,6 +606,16 @@ version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + [[package]] name = "mio" version = "0.7.13" @@ -471,6 +644,16 @@ version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" +[[package]] +name = "nom" +version = "4.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ad2a91a8e869eeb30b9cb3119ae87773a8f4ae617f41b1eb9c154b2905f7bd6" +dependencies = [ + "memchr", + "version_check 0.1.5", +] + [[package]] name = "normalize-line-endings" version = "0.3.0" @@ -493,7 +676,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bafe4179722c2894288ee77a9f044f02811c86af699344c498b0840c698a2465" dependencies = [ "arrayvec", + "cfg-if 0.1.10", + "encoding_rs", "itoa", + "lazy_static", + "libc", + "num-format-windows", + "widestring", + "winapi", +] + +[[package]] +name = "num-format-windows" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e179850c4611faf725cc7d92016aa9261a4c9887fc5501812da6cb87297c5eb" +dependencies = [ + "bindgen", ] [[package]] @@ -515,6 +714,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "object" +version = "0.27.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67ac1d3f9a1d3616fd9a60c8d74296f22406a238b6a72f5cc1e6f314df4ffbf9" +dependencies = [ + "memchr", +] + [[package]] name = "once_cell" version = "1.8.0" @@ -538,7 +746,7 @@ version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "instant", "libc", "redox_syscall", @@ -546,6 +754,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "peeking_take_while" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099" + [[package]] name = "ppv-lite86" version = "0.2.10" @@ -592,13 +806,37 @@ dependencies = [ "treeline", ] +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +dependencies = [ + "unicode-xid 0.1.0", +] + [[package]] name = "proc-macro2" version = "1.0.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c7ed8b8c7b886ea3ed7dde405212185f423ab44682667c8c6dd14aa1d9f6612" dependencies = [ - "unicode-xid", + "unicode-xid 0.2.2", +] + +[[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" +dependencies = [ + "proc-macro2 0.4.30", ] [[package]] @@ -607,7 +845,7 @@ version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ - "proc-macro2", + "proc-macro2 1.0.28", ] [[package]] @@ -701,6 +939,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "rustc-demangle" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ef03e0a2b150c7a90d01faf6254c9c48a41e95fb2a8c2ac1c6f0d2b9aefc342" + [[package]] name = "same-file" version = "1.0.6" @@ -710,6 +954,12 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" + [[package]] name = "scopeguard" version = "1.1.0" @@ -731,8 +981,8 @@ version = "1.0.129" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e57ae87ad533d9a56427558b516d0adac283614e347abf85b0dc0cbbf0a249f3" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.28", + "quote 1.0.9", "syn", ] @@ -765,11 +1015,17 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5" dependencies = [ - "proc-macro2", - "quote", + "proc-macro2 1.0.28", + "quote 1.0.9", "syn", ] +[[package]] +name = "shlex" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fdf1b9db47230893d76faad238fd6097fd6d6a9245cd7a4d90dbd639536bbd2" + [[package]] name = "signal-hook" version = "0.3.9" @@ -818,9 +1074,9 @@ version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f58f7e8eaa0009c5fec437aabf511bd9933e4b2d7407bd05273c01a8906ea7" dependencies = [ - "proc-macro2", - "quote", - "unicode-xid", + "proc-macro2 1.0.28", + "quote 1.0.9", + "unicode-xid 0.2.2", ] [[package]] @@ -829,7 +1085,7 @@ version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" dependencies = [ - "cfg-if", + "cfg-if 1.0.0", "libc", "rand", "redox_syscall", @@ -856,6 +1112,15 @@ dependencies = [ "winapi", ] +[[package]] +name = "termcolor" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dfed899f0eb03f32ee8c6a0aabdb8a7949659e3466561fc0adf54e26d88c5f4" +dependencies = [ + "winapi-util", +] + [[package]] name = "terminal_size" version = "0.1.17" @@ -907,6 +1172,12 @@ version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9337591893a19b88d8d87f2cec1e73fad5cdfd10e5a6f349f498ad6ea2ffb1e3" +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" + [[package]] name = "unicode-xid" version = "0.2.2" @@ -929,6 +1200,12 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1bddf1187be692e79c5ffeab891132dfb0f236ed36a43c7ed39f1165ee20191" +[[package]] +name = "version_check" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "914b1a6776c4c929a602fafd8bc742e06365d4bcbe48c30f9cca5824f70dc9dd" + [[package]] name = "version_check" version = "0.9.3" @@ -961,13 +1238,29 @@ version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +[[package]] +name = "which" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b57acb10231b9493c8472b20cb57317d0679a49e0bdbee44b3b803a6473af164" +dependencies = [ + "failure", + "libc", +] + +[[package]] +name = "widestring" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" + [[package]] name = "wild" version = "2.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "035793abb854745033f01a07647a79831eba29ec0be377205f2a25b0aa830020" dependencies = [ - "glob", + "glob 0.3.0", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 4d0207956..d41f30aa8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,13 +37,14 @@ xdg = "2.1.*" yaml-rust = "0.4.*" serde = { version = "1.0", features = ["derive"] } serde_yaml = "0.8" -num-format = "0.4.0" [target.'cfg(unix)'.dependencies] +num-format = { version = "0.4", features = ["with-system-locale"] } users = "0.11.*" [target.'cfg(windows)'.dependencies] winapi = {version = "0.3.*", features = ["aclapi", "accctrl", "winnt", "winerror", "securitybaseapi", "winbase"]} +num-format = { version = "0.4" } [dependencies.clap] features = ["suggestions", "color", "wrap_help"] diff --git a/src/meta/size.rs b/src/meta/size.rs index 9e9831335..de390b4cd 100644 --- a/src/meta/size.rs +++ b/src/meta/size.rs @@ -1,8 +1,8 @@ use crate::color::{ColoredString, Colors, Elem}; use crate::flags::{Flags, SizeFlag}; -use num_format::{Locale, ToFormattedString}; use std::fs::Metadata; use std::iter::repeat; +use num_format::{ToFormattedString}; #[derive(Clone, Debug, PartialEq, Eq)] pub enum Unit { @@ -41,12 +41,26 @@ impl Size { fn format_bytes(&self, flags: &Flags) -> String { if flags.size == SizeFlag::BytesWithSeparator { - self.bytes.to_formatted_string(&Locale::en) + self.os_formatted_bytes() } else { self.bytes.to_string() } } + #[cfg(unix)] + fn os_formatted_bytes(&self) -> String { + if let Ok(system_locale) = num_format::SystemLocale::default() { + self.bytes.to_formatted_string(&system_locale) + } else { + self.bytes.to_formatted_string(&num_format::Locale::en) + } + } + + #[cfg(not(unix))] + fn os_formatted_bytes(&self) -> String { + self.bytes.to_formatted_string(&Locale::en) + } + pub fn get_unit(&self, flags: &Flags) -> Unit { if self.bytes < 1024 || flags.size == SizeFlag::Bytes @@ -170,6 +184,7 @@ impl Size { #[cfg(test)] mod test { + use std::env; use super::Size; use crate::color::{Colors, ThemeOption}; use crate::flags::{Flags, SizeFlag}; @@ -349,6 +364,23 @@ mod test { assert_eq!(size.render(&colors, &flags, Some(3)).to_string(), " 42K"); } + #[cfg(unix)] + #[test] + fn render_bytes_with_separator() { + env::set_var("LC_ALL", "en"); + let size = Size::new(42 * 1024 * 1024); // == 42 megabytes + let mut flags = Flags::default(); + + flags.size = SizeFlag::Bytes; + assert_eq!(size.value_string(&flags).as_str(), "44040192"); + assert_eq!(size.unit_string(&flags).as_str(), ""); + + flags.size = SizeFlag::BytesWithSeparator; + assert_eq!(size.value_string(&flags).as_str(), "44,040,192"); + assert_eq!(size.unit_string(&flags).as_str(), ""); + } + + #[cfg(not(unix))] #[test] fn render_bytes_with_separator() { let size = Size::new(42 * 1024 * 1024); // == 42 megabytes From 6f1b202b8339ef8ee5aa7408628abdc7e6853bac Mon Sep 17 00:00:00 2001 From: Arkadiusz Bielewicz Date: Thu, 4 Nov 2021 12:03:36 +0100 Subject: [PATCH 9/9] #533 thousands separator for the --size=bytes option would be very useful | Potential fix for unix musl --- src/meta/size.rs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/meta/size.rs b/src/meta/size.rs index de390b4cd..6a26cbcb4 100644 --- a/src/meta/size.rs +++ b/src/meta/size.rs @@ -1,8 +1,8 @@ use crate::color::{ColoredString, Colors, Elem}; use crate::flags::{Flags, SizeFlag}; +use num_format::ToFormattedString; use std::fs::Metadata; use std::iter::repeat; -use num_format::{ToFormattedString}; #[derive(Clone, Debug, PartialEq, Eq)] pub enum Unit { @@ -58,7 +58,7 @@ impl Size { #[cfg(not(unix))] fn os_formatted_bytes(&self) -> String { - self.bytes.to_formatted_string(&Locale::en) + self.bytes.to_formatted_string(&num_format::Locale::en) } pub fn get_unit(&self, flags: &Flags) -> Unit { @@ -184,10 +184,10 @@ impl Size { #[cfg(test)] mod test { - use std::env; use super::Size; use crate::color::{Colors, ThemeOption}; use crate::flags::{Flags, SizeFlag}; + use std::env; #[test] fn render_byte() { @@ -367,7 +367,8 @@ mod test { #[cfg(unix)] #[test] fn render_bytes_with_separator() { - env::set_var("LC_ALL", "en"); + env::set_var("LC_ALL", "en-US"); + env::set_var("LC_NUMERIC", ","); let size = Size::new(42 * 1024 * 1024); // == 42 megabytes let mut flags = Flags::default();