diff --git a/crates/nu-command/src/random/dice.rs b/crates/nu-command/src/random/dice.rs new file mode 100644 index 0000000000..de44f2f35c --- /dev/null +++ b/crates/nu-command/src/random/dice.rs @@ -0,0 +1,98 @@ +use nu_engine::CallExt; +use nu_protocol::ast::Call; +use nu_protocol::engine::{Command, EngineState, Stack}; +use nu_protocol::{ + Category, Example, PipelineData, ShellError, Signature, SyntaxShape, Value, ValueStream, +}; +use rand::prelude::{thread_rng, Rng}; + +#[derive(Clone)] +pub struct SubCommand; + +impl Command for SubCommand { + fn name(&self) -> &str { + "random dice" + } + + fn signature(&self) -> Signature { + Signature::build("random dice") + .named( + "dice", + SyntaxShape::Int, + "The amount of dice being rolled", + Some('d'), + ) + .named( + "sides", + SyntaxShape::Int, + "The amount of sides a die has", + Some('s'), + ) + .category(Category::Random) + } + + fn usage(&self) -> &str { + "Generate a random dice roll" + } + + fn run( + &self, + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, + _input: PipelineData, + ) -> Result { + dice(engine_state, stack, call) + } + + fn examples(&self) -> Vec { + vec![ + Example { + description: "Roll 1 dice with 6 sides each", + example: "random dice", + result: None, + }, + Example { + description: "Roll 10 dice with 12 sides each", + example: "random dice -d 10 -s 12", + result: None, + }, + ] + } +} + +fn dice( + engine_state: &EngineState, + stack: &mut Stack, + call: &Call, +) -> Result { + let span = call.head; + + let dice: usize = call.get_flag(engine_state, stack, "dice")?.unwrap_or(1); + let sides: usize = call.get_flag(engine_state, stack, "sides")?.unwrap_or(6); + + let iter = (0..dice).map(move |_| { + let mut thread_rng = thread_rng(); + Value::Int { + val: thread_rng.gen_range(1..sides + 1) as i64, + span, + } + }); + + Ok(PipelineData::Stream( + ValueStream::from_stream(iter, engine_state.ctrlc.clone()), + 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/mod.rs b/crates/nu-command/src/random/mod.rs index c199b66a9a..b13a0834e0 100644 --- a/crates/nu-command/src/random/mod.rs +++ b/crates/nu-command/src/random/mod.rs @@ -2,8 +2,10 @@ mod bool; mod chars; mod command; mod decimal; +mod dice; pub use self::bool::SubCommand as Bool; pub use self::chars::SubCommand as Chars; pub use self::decimal::SubCommand as Decimal; +pub use self::dice::SubCommand as Dice; pub use command::RandomCommand as Random;