forked from extern/nushell
nu-cli refactor moving commands into their own crate nu-command (#2910)
* move commands, futures.rs, script.rs, utils * move over maybe_print_errors * add nu_command crate references to nu_cli * in commands.rs open up to pub mod from pub(crate) * nu-cli, nu-command, and nu tests are now passing * cargo fmt * clean up nu-cli/src/prelude.rs * code cleanup * for some reason lex.rs was not formatted, may be causing my error * remove mod completion from lib.rs which was not being used along with quickcheck macros * add in allow unused imports * comment out one failing external test; comment out one failing internal test * revert commenting out failing tests; something else might be going on; someone with a windows machine should check and see what is going on with these failing windows tests * Update Cargo.toml Extend the optional features to nu-command Co-authored-by: Jonathan Turner <jonathandturner@users.noreply.github.com>
This commit is contained in:
104
crates/nu-command/src/commands/math/round.rs
Normal file
104
crates/nu-command/src/commands/math/round.rs
Normal file
@ -0,0 +1,104 @@
|
||||
use crate::prelude::*;
|
||||
use nu_engine::WholeStreamCommand;
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value};
|
||||
use nu_source::Tagged;
|
||||
|
||||
pub struct SubCommand;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Arguments {
|
||||
precision: Option<Tagged<i64>>,
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl WholeStreamCommand for SubCommand {
|
||||
fn name(&self) -> &str {
|
||||
"math round"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("math round").named(
|
||||
"precision",
|
||||
SyntaxShape::Number,
|
||||
"digits of precision",
|
||||
Some('p'),
|
||||
)
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Applies the round function to a list of numbers"
|
||||
}
|
||||
|
||||
async fn run(&self, args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
operate(args).await
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
vec![
|
||||
Example {
|
||||
description: "Apply the round function to a list of numbers",
|
||||
example: "echo [1.5 2.3 -3.1] | math round",
|
||||
result: Some(vec![
|
||||
UntaggedValue::int(2).into(),
|
||||
UntaggedValue::int(2).into(),
|
||||
UntaggedValue::int(-3).into(),
|
||||
]),
|
||||
},
|
||||
Example {
|
||||
description: "Apply the round function with precision specified",
|
||||
example: "echo [1.555 2.333 -3.111] | math round -p 2",
|
||||
result: Some(vec![
|
||||
UntaggedValue::decimal_from_float(1.56, Span::default()).into(),
|
||||
UntaggedValue::decimal_from_float(2.33, Span::default()).into(),
|
||||
UntaggedValue::decimal_from_float(-3.11, Span::default()).into(),
|
||||
]),
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
async fn operate(args: CommandArgs) -> Result<OutputStream, ShellError> {
|
||||
let (Arguments { precision }, input) = args.process().await?;
|
||||
let precision = precision.map(|p| p.item).unwrap_or(0);
|
||||
|
||||
let mapped = input.map(move |val| match val.value {
|
||||
UntaggedValue::Primitive(Primitive::Int(val)) => round_big_int(val),
|
||||
UntaggedValue::Primitive(Primitive::Decimal(val)) => round_big_decimal(val, precision),
|
||||
other => round_default(other),
|
||||
});
|
||||
Ok(OutputStream::from_input(mapped))
|
||||
}
|
||||
|
||||
fn round_big_int(val: BigInt) -> Value {
|
||||
UntaggedValue::int(val).into()
|
||||
}
|
||||
|
||||
fn round_big_decimal(val: BigDecimal, precision: i64) -> Value {
|
||||
if precision > 0 {
|
||||
UntaggedValue::decimal(val.round(precision)).into()
|
||||
} else {
|
||||
let (rounded, _) = val.round(precision).as_bigint_and_exponent();
|
||||
UntaggedValue::int(rounded).into()
|
||||
}
|
||||
}
|
||||
|
||||
fn round_default(_: UntaggedValue) -> Value {
|
||||
UntaggedValue::Error(ShellError::unexpected(
|
||||
"Only numerical values are supported",
|
||||
))
|
||||
.into()
|
||||
}
|
||||
|
||||
#[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 {})?)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user