From 5fb3df4054b7a2c333a57f91553b7016194aea3a Mon Sep 17 00:00:00 2001 From: smaydew <65190294+smaydew@users.noreply.github.com> Date: Tue, 24 Nov 2020 02:19:48 -0700 Subject: [PATCH] Initial implementation of the random decimal subcommand. (#2762) Co-authored-by: Stacy Maydew --- crates/nu-cli/src/cli.rs | 1 + crates/nu-cli/src/commands.rs | 2 +- crates/nu-cli/src/commands/random/decimal.rs | 111 ++++++++++++++++++ crates/nu-cli/src/commands/random/mod.rs | 2 + .../nu-cli/tests/commands/random/decimal.rs | 37 ++++++ crates/nu-cli/tests/commands/random/mod.rs | 1 + 6 files changed, 153 insertions(+), 1 deletion(-) create mode 100644 crates/nu-cli/src/commands/random/decimal.rs create mode 100644 crates/nu-cli/tests/commands/random/decimal.rs diff --git a/crates/nu-cli/src/cli.rs b/crates/nu-cli/src/cli.rs index e8ffa41bd..9f22f2293 100644 --- a/crates/nu-cli/src/cli.rs +++ b/crates/nu-cli/src/cli.rs @@ -263,6 +263,7 @@ pub fn create_default_context(interactive: bool) -> Result>, +} + +#[async_trait] +impl WholeStreamCommand for SubCommand { + fn name(&self) -> &str { + "random decimal" + } + + fn signature(&self) -> Signature { + Signature::build("random decimal").optional("range", SyntaxShape::Range, "Range of values") + } + + fn usage(&self) -> &str { + "Generate a random decimal within a range [min..max]" + } + + async fn run( + &self, + args: CommandArgs, + registry: &CommandRegistry, + ) -> Result { + decimal(args, registry).await + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Generate a default decimal value between 0 and 1", + example: "random decimal", + result: None, + }, + Example { + description: "Generate a random decimal less than or equal to 500", + example: "random decimal ..500", + result: None, + }, + Example { + description: "Generate a random decimal greater than or equal to 100000", + example: "random decimal 100000..", + result: None, + }, + Example { + description: "Generate a random decimal between 1 and 10", + example: "random decimal 1..10", + result: None, + }, + ] + } +} + +pub async fn decimal( + args: CommandArgs, + registry: &CommandRegistry, +) -> Result { + let (DecimalArgs { range }, _) = args.process(®istry).await?; + + let (min, max) = if let Some(range) = &range { + (range.item.min() as f64, range.item.max() as f64) + } else { + (0.0, 1.0) + }; + + match min.partial_cmp(&max) { + Some(Ordering::Greater) => Err(ShellError::labeled_error( + format!("Invalid range {}..{}", min, max), + "expected a valid range", + range + .expect("Unexpected ordering error in random decimal") + .span(), + )), + Some(Ordering::Equal) => { + let untagged_result = UntaggedValue::decimal_from_float(min, Span::new(64, 64)); + Ok(OutputStream::one(ReturnSuccess::value(untagged_result))) + } + _ => { + let mut thread_rng = thread_rng(); + let result: f64 = thread_rng.gen_range(min, max); + + let untagged_result = UntaggedValue::decimal_from_float(result, Span::new(64, 64)); + + Ok(OutputStream::one(ReturnSuccess::value(untagged_result))) + } + } +} + +#[cfg(test)] +mod tests { + use super::ShellError; + use super::SubCommand; + + #[test] + fn examples_work_as_expected() -> Result<(), ShellError> { + use crate::examples::test as test_examples; + + Ok(test_examples(SubCommand {})?) + } +} diff --git a/crates/nu-cli/src/commands/random/mod.rs b/crates/nu-cli/src/commands/random/mod.rs index 3cd4d14eb..330173b42 100644 --- a/crates/nu-cli/src/commands/random/mod.rs +++ b/crates/nu-cli/src/commands/random/mod.rs @@ -1,6 +1,7 @@ pub mod command; pub mod bool; +pub mod decimal; pub mod dice; pub mod integer; #[cfg(feature = "uuid_crate")] @@ -9,6 +10,7 @@ pub mod uuid; pub use command::Command as Random; pub use self::bool::SubCommand as RandomBool; +pub use decimal::SubCommand as RandomDecimal; pub use dice::SubCommand as RandomDice; pub use integer::SubCommand as RandomInteger; #[cfg(feature = "uuid_crate")] diff --git a/crates/nu-cli/tests/commands/random/decimal.rs b/crates/nu-cli/tests/commands/random/decimal.rs new file mode 100644 index 000000000..0e78509a7 --- /dev/null +++ b/crates/nu-cli/tests/commands/random/decimal.rs @@ -0,0 +1,37 @@ +use nu_test_support::{nu, pipeline}; + +#[test] +fn generates_an_decimal() { + let actual = nu!( + cwd: ".", pipeline( + r#" + random decimal 42..43 + "# + )); + + assert!(actual.out.contains("42") || actual.out.contains("43")); +} + +#[test] +fn generates_55() { + let actual = nu!( + cwd: ".", pipeline( + r#" + random decimal 55..55 + "# + )); + + assert!(actual.out.contains("55")); +} + +#[test] +fn generates_0() { + let actual = nu!( + cwd: ".", pipeline( + r#" + random decimal ..<1 + "# + )); + + assert!(actual.out.contains('0')); +} diff --git a/crates/nu-cli/tests/commands/random/mod.rs b/crates/nu-cli/tests/commands/random/mod.rs index 7b7b33064..f3e765602 100644 --- a/crates/nu-cli/tests/commands/random/mod.rs +++ b/crates/nu-cli/tests/commands/random/mod.rs @@ -1,4 +1,5 @@ mod bool; +mod decimal; mod dice; mod integer; #[cfg(feature = "uuid_crate")]