add random commands (#366)

* feat: add random command

* feat: add bool sub-command
This commit is contained in:
Jae-Heon Ji 2021-11-30 15:12:19 +09:00 committed by GitHub
parent ce4d9dc7c6
commit 21ddfc61f4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 154 additions and 1 deletions

View File

@ -114,6 +114,7 @@ pub fn create_default_context() -> EngineState {
Parse,
Ps,
Range,
Random,
Reverse,
Rm,
Select,

View File

@ -7,7 +7,7 @@ use nu_protocol::{
use crate::To;
use super::{Date, From, Into, Math, Split, Str};
use super::{Date, From, Into, Math, Random, Split, Str};
pub fn test_examples(cmd: impl Command + 'static) {
let examples = cmd.examples();
@ -21,6 +21,7 @@ pub fn test_examples(cmd: impl Command + 'static) {
working_set.add_decl(Box::new(From));
working_set.add_decl(Box::new(To));
working_set.add_decl(Box::new(Into));
working_set.add_decl(Box::new(Random));
working_set.add_decl(Box::new(Split));
working_set.add_decl(Box::new(Math));
working_set.add_decl(Box::new(Date));

View File

@ -10,6 +10,7 @@ mod filters;
mod formats;
mod math;
mod platform;
mod random;
mod shells;
mod strings;
mod system;
@ -30,6 +31,7 @@ pub use filters::*;
pub use formats::*;
pub use math::*;
pub use platform::*;
pub use random::*;
pub use shells::*;
pub use strings::*;
pub use system::*;

View File

@ -0,0 +1,97 @@
use nu_engine::CallExt;
use nu_protocol::ast::Call;
use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{
Category, Example, PipelineData, ShellError, Signature, Spanned, SyntaxShape, Value,
};
use rand::prelude::{thread_rng, Rng};
#[derive(Clone)]
pub struct SubCommand;
impl Command for SubCommand {
fn name(&self) -> &str {
"random bool"
}
fn signature(&self) -> Signature {
Signature::build("random bool")
.named(
"bias",
SyntaxShape::Number,
"Adjusts the probability of a \"true\" outcome",
Some('b'),
)
.category(Category::Random)
}
fn usage(&self) -> &str {
"Generate a random boolean value"
}
fn run(
&self,
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
_input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
bool(engine_state, stack, call)
}
fn examples(&self) -> Vec<Example> {
vec![
Example {
description: "Generate a random boolean value",
example: "random bool",
result: None,
},
Example {
description: "Generate a random boolean value with a 75% chance of \"true\"",
example: "random bool --bias 0.75",
result: None,
},
]
}
}
fn bool(
engine_state: &EngineState,
stack: &mut Stack,
call: &Call,
) -> Result<PipelineData, ShellError> {
let span = call.head;
let bias: Option<Spanned<f64>> = call.get_flag(engine_state, stack, "bias")?;
let mut probability = 0.5;
if let Some(prob) = bias {
probability = prob.item;
let probability_is_valid = (0.0..=1.0).contains(&probability);
if !probability_is_valid {
return Err(ShellError::InvalidProbability(prob.span));
}
}
let mut rng = thread_rng();
let bool_result: bool = rng.gen_bool(probability);
Ok(PipelineData::Value(Value::Bool {
val: bool_result,
span,
}))
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_examples() {
use crate::test_examples;
test_examples(SubCommand {})
}
}

View File

@ -0,0 +1,41 @@
use nu_engine::get_full_help;
use nu_protocol::{
ast::Call,
engine::{Command, EngineState, Stack},
Category, IntoPipelineData, PipelineData, Signature, Value,
};
#[derive(Clone)]
pub struct RandomCommand;
impl Command for RandomCommand {
fn name(&self) -> &str {
"random"
}
fn signature(&self) -> Signature {
Signature::build("random").category(Category::Random)
}
fn usage(&self) -> &str {
"Generate a random values."
}
fn run(
&self,
engine_state: &EngineState,
_stack: &mut Stack,
call: &Call,
_input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
Ok(Value::String {
val: get_full_help(
&RandomCommand.signature(),
&RandomCommand.examples(),
engine_state,
),
span: call.head,
}
.into_pipeline_data())
}
}

View File

@ -0,0 +1,5 @@
mod bool;
mod command;
pub use self::bool::SubCommand as Bool;
pub use command::RandomCommand as Random;

View File

@ -76,6 +76,10 @@ pub enum ShellError {
#[diagnostic(code(nu::shell::external_commands), url(docsrs))]
ExternalNotSupported(#[label = "external not supported"] Span),
#[error("Invalid Probability.")]
#[diagnostic(code(nu::shell::invalid_probability), url(docsrs))]
InvalidProbability(#[label = "invalid probability"] Span),
#[error("Internal error: {0}.")]
#[diagnostic(code(nu::shell::internal_error), url(docsrs))]
InternalError(String),

View File

@ -42,6 +42,7 @@ pub enum Category {
Filters,
Formats,
Math,
Random,
Platform,
Shells,
Strings,
@ -63,6 +64,7 @@ impl std::fmt::Display for Category {
Category::Filters => "filters",
Category::Formats => "formats",
Category::Math => "math",
Category::Random => "random",
Category::Platform => "platform",
Category::Shells => "shells",
Category::Strings => "strings",