Skip to content

Commit 6d6b050

Browse files
authored
Merge pull request #10108 from ChrisDryden/numfmt-unit-separator
numfmt: add --unit-separator option for output formatting
2 parents 755b7eb + 929bb34 commit 6d6b050

File tree

5 files changed

+39
-3
lines changed

5 files changed

+39
-3
lines changed

src/uu/numfmt/locales/en-US.ftl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ numfmt-help-padding = pad the output to N characters; positive N will right-alig
4747
numfmt-help-header = print (without converting) the first N header lines; N defaults to 1 if not specified
4848
numfmt-help-round = use METHOD for rounding when scaling
4949
numfmt-help-suffix = print SUFFIX after each formatted number, and accept inputs optionally ending with SUFFIX
50+
numfmt-help-unit-separator = use STRING to separate the number from any unit when printing; by default, no separator is used
5051
numfmt-help-invalid = set the failure mode for invalid input
5152
numfmt-help-zero-terminated = line delimiter is NUL, not newline
5253

src/uu/numfmt/src/format.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -275,6 +275,7 @@ fn transform_to(
275275
opts: &TransformOptions,
276276
round_method: RoundMethod,
277277
precision: usize,
278+
unit_separator: &str,
278279
) -> Result<String> {
279280
let (i2, s) = consider_suffix(s, &opts.to, round_method, precision)?;
280281
let i2 = i2 / (opts.to_unit as f64);
@@ -286,10 +287,15 @@ fn transform_to(
286287
)
287288
}
288289
Some(s) if precision > 0 => {
289-
format!("{i2:.precision$}{}", DisplayableSuffix(s, opts.to),)
290+
format!(
291+
"{i2:.precision$}{unit_separator}{}",
292+
DisplayableSuffix(s, opts.to),
293+
)
294+
}
295+
Some(s) if i2.abs() < 10.0 => {
296+
format!("{i2:.1}{unit_separator}{}", DisplayableSuffix(s, opts.to))
290297
}
291-
Some(s) if i2.abs() < 10.0 => format!("{i2:.1}{}", DisplayableSuffix(s, opts.to)),
292-
Some(s) => format!("{i2:.0}{}", DisplayableSuffix(s, opts.to)),
298+
Some(s) => format!("{i2:.0}{unit_separator}{}", DisplayableSuffix(s, opts.to)),
293299
})
294300
}
295301

@@ -317,6 +323,7 @@ fn format_string(
317323
&options.transform,
318324
options.round,
319325
precision,
326+
&options.unit_separator,
320327
)?;
321328

322329
// bring back the suffix before applying padding

src/uu/numfmt/src/numfmt.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,11 @@ fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
234234

235235
let suffix = args.get_one::<String>(SUFFIX).cloned();
236236

237+
let unit_separator = args
238+
.get_one::<String>(UNIT_SEPARATOR)
239+
.cloned()
240+
.unwrap_or_default();
241+
237242
let invalid = InvalidModes::from_str(args.get_one::<String>(INVALID).unwrap()).unwrap();
238243

239244
let zero_terminated = args.get_flag(ZERO_TERMINATED);
@@ -246,6 +251,7 @@ fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
246251
delimiter,
247252
round,
248253
suffix,
254+
unit_separator,
249255
format,
250256
invalid,
251257
zero_terminated,
@@ -370,6 +376,12 @@ pub fn uu_app() -> Command {
370376
.help(translate!("numfmt-help-suffix"))
371377
.value_name("SUFFIX"),
372378
)
379+
.arg(
380+
Arg::new(UNIT_SEPARATOR)
381+
.long(UNIT_SEPARATOR)
382+
.help(translate!("numfmt-help-unit-separator"))
383+
.value_name("STRING"),
384+
)
373385
.arg(
374386
Arg::new(INVALID)
375387
.long(INVALID)
@@ -419,6 +431,7 @@ mod tests {
419431
delimiter: None,
420432
round: RoundMethod::Nearest,
421433
suffix: None,
434+
unit_separator: String::new(),
422435
format: FormatOptions::default(),
423436
invalid: InvalidModes::Abort,
424437
zero_terminated: false,

src/uu/numfmt/src/options.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub const TO: &str = "to";
2727
pub const TO_DEFAULT: &str = "none";
2828
pub const TO_UNIT: &str = "to-unit";
2929
pub const TO_UNIT_DEFAULT: &str = "1";
30+
pub const UNIT_SEPARATOR: &str = "unit-separator";
3031
pub const ZERO_TERMINATED: &str = "zero-terminated";
3132

3233
pub struct TransformOptions {
@@ -52,6 +53,7 @@ pub struct NumfmtOptions {
5253
pub delimiter: Option<String>,
5354
pub round: RoundMethod,
5455
pub suffix: Option<String>,
56+
pub unit_separator: String,
5557
pub format: FormatOptions,
5658
pub invalid: InvalidModes,
5759
pub zero_terminated: bool,

tests/by-util/test_numfmt.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1115,3 +1115,16 @@ fn test_zero_terminated_embedded_newline() {
11151115
// Newlines get replaced by a single space
11161116
.stdout_is("1000 2000\x003000 4000\x00");
11171117
}
1118+
1119+
#[test]
1120+
fn test_unit_separator() {
1121+
for (args, expected) in [
1122+
(&["--to=si", "--unit-separator= ", "1000"][..], "1.0 k\n"),
1123+
(&["--to=iec", "--unit-separator= ", "1024"], "1.0 K\n"),
1124+
(&["--to=iec-i", "--unit-separator= ", "2048"], "2.0 Ki\n"),
1125+
(&["--to=si", "--unit-separator=__", "1000"], "1.0__k\n"),
1126+
(&["--to=si", "--unit-separator= ", "500"], "500\n"), // no unit = no separator
1127+
] {
1128+
new_ucmd!().args(args).succeeds().stdout_only(expected);
1129+
}
1130+
}

0 commit comments

Comments
 (0)