Merge pull request #2841 from sbentmar/add-suffix-to-numfmt

numfmt: implement missing --suffix option
This commit is contained in:
Sylvestre Ledru 2022-01-02 23:07:29 +01:00 committed by GitHub
commit cd1a0fbe36
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 97 additions and 4 deletions

View file

@ -220,16 +220,32 @@ fn format_string(
options: &NumfmtOptions,
implicit_padding: Option<isize>,
) -> Result<String> {
// strip the (optional) suffix before applying any transformation
let source_without_suffix = match &options.suffix {
Some(suffix) => source.strip_suffix(suffix).unwrap_or(source),
None => source,
};
let number = transform_to(
transform_from(source, &options.transform.from)?,
transform_from(source_without_suffix, &options.transform.from)?,
&options.transform.to,
options.round,
)?;
// bring back the suffix before applying padding
let number_with_suffix = match &options.suffix {
Some(suffix) => format!("{}{}", number, suffix),
None => number,
};
Ok(match implicit_padding.unwrap_or(options.padding) {
0 => number,
p if p > 0 => format!("{:>padding$}", number, padding = p as usize),
p => format!("{:<padding$}", number, padding = p.abs() as usize),
0 => number_with_suffix,
p if p > 0 => format!("{:>padding$}", number_with_suffix, padding = p as usize),
p => format!(
"{:<padding$}",
number_with_suffix,
padding = p.abs() as usize
),
})
}

View file

@ -142,6 +142,8 @@ fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
_ => unreachable!("Should be restricted by clap"),
};
let suffix = args.value_of(options::SUFFIX).map(|s| s.to_owned());
Ok(NumfmtOptions {
transform,
padding,
@ -149,6 +151,7 @@ fn parse_options(args: &ArgMatches) -> Result<NumfmtOptions> {
fields,
delimiter,
round,
suffix,
})
}
@ -242,5 +245,14 @@ pub fn uu_app() -> App<'static, 'static> {
.default_value("from-zero")
.possible_values(&["up", "down", "from-zero", "towards-zero", "nearest"]),
)
.arg(
Arg::with_name(options::SUFFIX)
.long(options::SUFFIX)
.help(
"print SUFFIX after each formatted number, and accept \
inputs optionally ending with SUFFIX",
)
.value_name("SUFFIX"),
)
.arg(Arg::with_name(options::NUMBER).hidden(true).multiple(true))
}

View file

@ -11,6 +11,7 @@ pub const HEADER_DEFAULT: &str = "1";
pub const NUMBER: &str = "NUMBER";
pub const PADDING: &str = "padding";
pub const ROUND: &str = "round";
pub const SUFFIX: &str = "suffix";
pub const TO: &str = "to";
pub const TO_DEFAULT: &str = "none";
@ -26,6 +27,7 @@ pub struct NumfmtOptions {
pub fields: Vec<Range>,
pub delimiter: Option<String>,
pub round: RoundMethod,
pub suffix: Option<String>,
}
#[derive(Clone, Copy)]

View file

@ -505,3 +505,66 @@ fn test_round() {
.stdout_only(exp.join("\n") + "\n");
}
}
#[test]
fn test_suffix_is_added_if_not_supplied() {
new_ucmd!()
.args(&["--suffix=TEST"])
.pipe_in("1000")
.succeeds()
.stdout_only("1000TEST\n");
}
#[test]
fn test_suffix_is_preserved() {
new_ucmd!()
.args(&["--suffix=TEST"])
.pipe_in("1000TEST")
.succeeds()
.stdout_only("1000TEST\n");
}
#[test]
fn test_suffix_is_only_applied_to_selected_field() {
new_ucmd!()
.args(&["--suffix=TEST", "--field=2"])
.pipe_in("1000 2000 3000")
.succeeds()
.stdout_only("1000 2000TEST 3000\n");
}
#[test]
fn test_transform_with_suffix_on_input() {
new_ucmd!()
.args(&["--suffix=b", "--to=si"])
.pipe_in("2000b")
.succeeds()
.stdout_only("2.0Kb\n");
}
#[test]
fn test_transform_without_suffix_on_input() {
new_ucmd!()
.args(&["--suffix=b", "--to=si"])
.pipe_in("2000")
.succeeds()
.stdout_only("2.0Kb\n");
}
#[test]
fn test_transform_with_suffix_and_delimiter() {
new_ucmd!()
.args(&["--suffix=b", "--to=si", "-d=|"])
.pipe_in("1000b|2000|3000")
.succeeds()
.stdout_only("1.0Kb|2000|3000\n");
}
#[test]
fn test_suffix_with_padding() {
new_ucmd!()
.args(&["--suffix=pad", "--padding=12"])
.pipe_in("1000 2000 3000")
.succeeds()
.stdout_only(" 1000pad 2000 3000\n");
}