diff --git a/crates/nu-command/src/default_context.rs b/crates/nu-command/src/default_context.rs index aeedd4bed0cf7..ac5f7655ef3f1 100644 --- a/crates/nu-command/src/default_context.rs +++ b/crates/nu-command/src/default_context.rs @@ -370,6 +370,7 @@ pub fn add_shell_command_context(mut engine_state: EngineState) -> EngineState { RandomDecimal, RandomDice, RandomFloat, + RandomInt, RandomInteger, RandomUuid, }; diff --git a/crates/nu-command/src/random/int.rs b/crates/nu-command/src/random/int.rs new file mode 100644 index 0000000000000..4bbd7b7f75601 --- /dev/null +++ b/crates/nu-command/src/random/int.rs @@ -0,0 +1,116 @@ +use nu_engine::CallExt; +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{ + Category, Example, PipelineData, Range, ShellError, Signature, SyntaxShape, Type, Value, +}; +use rand::prelude::{thread_rng, Rng}; +use std::cmp::Ordering; + +#[derive(Clone)] +pub struct SubCommand; + +impl Command for SubCommand { + fn name(&self) -> &str { + "random int" + } + + fn signature(&self) -> Signature { + Signature::build("random int") + .input_output_types(vec![(Type::Nothing, Type::Int)]) + .allow_variants_without_examples(true) + .optional("range", SyntaxShape::Range, "Range of values") + .category(Category::Random) + } + + fn usage(&self) -> &str { + "Generate a random integer [min..max]." + } + + fn search_terms(&self) -> Vec<&str> { + vec!["generate", "natural", "number"] + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + integer(engine_state, stack, call) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Generate an unconstrained random integer", + example: "random int", + result: None, + }, + Example { + description: "Generate a random integer less than or equal to 500", + example: "random int ..500", + result: None, + }, + Example { + description: "Generate a random integer greater than or equal to 100000", + example: "random int 100000..", + result: None, + }, + Example { + description: "Generate a random integer between 1 and 10", + example: "random int 1..10", + result: None, + }, + ] + } +} + +fn integer( + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, +) -> Result { + let span = call.head; + let range: Option = call.opt(engine_state, stack, 0)?; + + let (min, max) = if let Some(r) = range { + if r.is_end_inclusive() { + (r.from.as_int()?, r.to.as_int()?) + } else if r.to.as_int()? > 0 { + (r.from.as_int()?, r.to.as_int()? - 1) + } else { + (0, 0) + } + } else { + (0, i64::MAX) + }; + + match min.partial_cmp(&max) { + Some(Ordering::Greater) => Err(ShellError::InvalidRange { + left_flank: min.to_string(), + right_flank: max.to_string(), + span, + }), + Some(Ordering::Equal) => Ok(PipelineData::Value(Value::int(min, span), None)), + _ => { + let mut thread_rng = thread_rng(); + let result: i64 = thread_rng.gen_range(min..=max); + + Ok(PipelineData::Value(Value::int(result, span), None)) + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn test_examples() { + use crate::test_examples; + + test_examples(SubCommand {}) + } +} diff --git a/crates/nu-command/src/random/integer.rs b/crates/nu-command/src/random/integer.rs index ed44e7cf210c9..821e791f6fc2a 100644 --- a/crates/nu-command/src/random/integer.rs +++ b/crates/nu-command/src/random/integer.rs @@ -24,7 +24,11 @@ impl Command for SubCommand { } fn usage(&self) -> &str { - "Generate a random integer [min..max]." + "deprecated: Generate a random integer [min..max]." + } + + fn extra_usage(&self) -> &str { + "Use `random int` instead" } fn search_terms(&self) -> Vec<&str> { @@ -38,6 +42,16 @@ impl Command for SubCommand { call: &Call, _input: PipelineData, ) -> Result { + nu_protocol::report_error_new( + engine_state, + &ShellError::GenericError( + "Deprecated command".into(), + "`random integer` is deprecated and will be removed in 0.87.".into(), + Some(call.head), + Some("Use `random int` instead".into()), + vec![], + ), + ); integer(engine_state, stack, call) } diff --git a/crates/nu-command/src/random/mod.rs b/crates/nu-command/src/random/mod.rs index 898aaa3fc9e1c..3a73a67e0d7ab 100644 --- a/crates/nu-command/src/random/mod.rs +++ b/crates/nu-command/src/random/mod.rs @@ -3,6 +3,7 @@ mod chars; mod decimal; mod dice; mod float; +mod int; mod integer; mod random_; mod uuid; @@ -12,6 +13,7 @@ pub use self::chars::SubCommand as RandomChars; pub use self::decimal::SubCommand as RandomDecimal; pub use self::dice::SubCommand as RandomDice; pub use self::float::SubCommand as RandomFloat; +pub use self::int::SubCommand as RandomInt; pub use self::integer::SubCommand as RandomInteger; pub use self::uuid::SubCommand as RandomUuid; pub use random_::RandomCommand as Random;