Merge pull request #1293 from JJJollyjim/master

numfmt: support neither or both of --to and --from
This commit is contained in:
Alex Lyon 2018-10-09 18:06:49 -07:00 committed by GitHub
commit 5008b4db2e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 54 additions and 30 deletions

View file

@ -34,17 +34,13 @@ const IEC_BASES: [f64; 10] = [
type Result<T> = std::result::Result<T, String>; type Result<T> = std::result::Result<T, String>;
enum TransformDirection {
From,
To,
}
type WithI = bool; type WithI = bool;
enum Unit { enum Unit {
Auto, Auto,
Si, Si,
Iec(WithI), Iec(WithI),
None,
} }
enum RawSuffix { enum RawSuffix {
@ -119,12 +115,17 @@ fn parse_unit(s: String) -> Result<Unit> {
"si" => Ok(Unit::Si), "si" => Ok(Unit::Si),
"iec" => Ok(Unit::Iec(false)), "iec" => Ok(Unit::Iec(false)),
"iec-i" => Ok(Unit::Iec(true)), "iec-i" => Ok(Unit::Iec(true)),
"none" => Ok(Unit::None),
_ => Err("Unsupported unit is specified".to_owned()), _ => Err("Unsupported unit is specified".to_owned()),
} }
} }
struct TransformOptions { struct TransformOptions {
direction: TransformDirection, from: Transform,
to: Transform,
}
struct Transform {
unit: Unit, unit: Unit,
} }
@ -165,9 +166,9 @@ fn remove_suffix(i: f64, s: Option<Suffix>, u: &Unit) -> Result<f64> {
} }
} }
fn transform_from(s: String, unit: &Unit) -> Result<String> { fn transform_from(s: String, opts: &Transform) -> Result<f64> {
let (i, suffix) = parse_suffix(s)?; let (i, suffix) = parse_suffix(s)?;
remove_suffix(i, suffix, unit).map(|n| n.round().to_string()) remove_suffix(i, suffix, &opts.unit).map(|n| n.round())
} }
fn consider_suffix(i: f64, u: &Unit) -> Result<(f64, Option<Suffix>)> { fn consider_suffix(i: f64, u: &Unit) -> Result<(f64, Option<Suffix>)> {
@ -198,12 +199,12 @@ fn consider_suffix(i: f64, u: &Unit) -> Result<(f64, Option<Suffix>)> {
_ => Err("Number is too big and unsupported".to_owned()), _ => Err("Number is too big and unsupported".to_owned()),
}, },
Unit::Auto => Err("Unit 'auto' isn't supported with --to options".to_owned()), Unit::Auto => Err("Unit 'auto' isn't supported with --to options".to_owned()),
Unit::None => Ok((i, None)),
} }
} }
fn transform_to(s: String, unit: &Unit) -> Result<String> { fn transform_to(s: f64, opts: &Transform) -> Result<String> {
let i = s.parse::<f64>().map_err(|err| err.to_string())?; let (i2, s) = consider_suffix(s, &opts.unit)?;
let (i2, s) = consider_suffix(i, unit)?;
Ok(match s { Ok(match s {
None => format!("{}", i2), None => format!("{}", i2),
Some(s) => format!("{:.1}{}", i2, DisplayableSuffix(s)), Some(s) => format!("{:.1}{}", i2, DisplayableSuffix(s)),
@ -211,10 +212,10 @@ fn transform_to(s: String, unit: &Unit) -> Result<String> {
} }
fn format_string(source: String, options: &NumfmtOptions) -> Result<String> { fn format_string(source: String, options: &NumfmtOptions) -> Result<String> {
let number = match options.transform.direction { let number = transform_to(
TransformDirection::From => transform_from(source, &options.transform.unit)?, transform_from(source, &options.transform.from)?,
TransformDirection::To => transform_to(source, &options.transform.unit)?, &options.transform.to,
}; )?;
Ok(match options.padding { Ok(match options.padding {
p if p == 0 => number, p if p == 0 => number,
@ -224,21 +225,19 @@ fn format_string(source: String, options: &NumfmtOptions) -> Result<String> {
} }
fn parse_options(args: &Matches) -> Result<NumfmtOptions> { fn parse_options(args: &Matches) -> Result<NumfmtOptions> {
let transform = if args.opt_present("from") { let transform = TransformOptions {
TransformOptions { from: Transform {
direction: TransformDirection::From, unit: args
unit: parse_unit( .opt_str("from")
args.opt_str("from") .map(parse_unit)
.ok_or("'--from' should have argument")?, .unwrap_or(Ok(Unit::None))?,
)?, },
} to: Transform {
} else if args.opt_present("to") { unit: args
TransformOptions { .opt_str("to")
direction: TransformDirection::To, .map(parse_unit)
unit: parse_unit(args.opt_str("to").ok_or("'--to' should have argument")?)?, .unwrap_or(Ok(Unit::None))?,
} },
} else {
return Err("Either '--from' or '--to' should be specified".to_owned());
}; };
let padding = match args.opt_str("padding") { let padding = match args.opt_str("padding") {

View file

@ -120,3 +120,28 @@ fn test_negative() {
.run() .run()
.stdout_is("-1.0Ki\n-1.1Mi\n-102.4Mi"); .stdout_is("-1.0Ki\n-1.1Mi\n-102.4Mi");
} }
#[test]
fn test_no_op() {
new_ucmd!()
.pipe_in("1024\n1234567")
.run()
.stdout_is("1024\n1234567");
}
#[test]
fn test_normalize() {
new_ucmd!()
.args(&["--from=si", "--to=si"])
.pipe_in("10000000K\n0.001K")
.run()
.stdout_is("10.0G\n1");
}
#[test]
fn test_si_to_iec() {
new_ucmd!()
.args(&["--from=si", "--to=iec", "15334263563K"])
.run()
.stdout_is("13.9T");
}