mirror of
https://github.com/nushell/nushell.git
synced 2025-02-17 02:50:56 +01:00
Precision added to round cmd (#2710)
This commit is contained in:
parent
c6fe58467b
commit
666fbbb0d1
@ -1,11 +1,16 @@
|
|||||||
use crate::commands::math::utils::run_with_numerical_functions_on_stream;
|
|
||||||
use crate::commands::WholeStreamCommand;
|
use crate::commands::WholeStreamCommand;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use nu_errors::ShellError;
|
use nu_errors::ShellError;
|
||||||
use nu_protocol::{Signature, UntaggedValue, Value};
|
use nu_protocol::{Primitive, Signature, SyntaxShape, UntaggedValue, Value};
|
||||||
|
use nu_source::Tagged;
|
||||||
|
|
||||||
pub struct SubCommand;
|
pub struct SubCommand;
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
struct Arguments {
|
||||||
|
precision: Option<Tagged<i64>>,
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl WholeStreamCommand for SubCommand {
|
impl WholeStreamCommand for SubCommand {
|
||||||
fn name(&self) -> &str {
|
fn name(&self) -> &str {
|
||||||
@ -13,7 +18,12 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn signature(&self) -> Signature {
|
fn signature(&self) -> Signature {
|
||||||
Signature::build("math round")
|
Signature::build("math round").named(
|
||||||
|
"precision",
|
||||||
|
SyntaxShape::Number,
|
||||||
|
"digits of precision",
|
||||||
|
Some('p'),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn usage(&self) -> &str {
|
fn usage(&self) -> &str {
|
||||||
@ -25,44 +35,59 @@ impl WholeStreamCommand for SubCommand {
|
|||||||
args: CommandArgs,
|
args: CommandArgs,
|
||||||
registry: &CommandRegistry,
|
registry: &CommandRegistry,
|
||||||
) -> Result<OutputStream, ShellError> {
|
) -> Result<OutputStream, ShellError> {
|
||||||
run_with_numerical_functions_on_stream(
|
operate(args, registry).await
|
||||||
RunnableContext {
|
|
||||||
input: args.input,
|
|
||||||
registry: registry.clone(),
|
|
||||||
shell_manager: args.shell_manager,
|
|
||||||
host: args.host,
|
|
||||||
ctrl_c: args.ctrl_c,
|
|
||||||
current_errors: args.current_errors,
|
|
||||||
name: args.call_info.name_tag,
|
|
||||||
raw_input: args.raw_input,
|
|
||||||
},
|
|
||||||
round_big_int,
|
|
||||||
round_big_decimal,
|
|
||||||
round_default,
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn examples(&self) -> Vec<Example> {
|
fn examples(&self) -> Vec<Example> {
|
||||||
vec![Example {
|
vec![
|
||||||
description: "Apply the round function to a list of numbers",
|
Example {
|
||||||
example: "echo [1.5 2.3 -3.1] | math round",
|
description: "Apply the round function to a list of numbers",
|
||||||
result: Some(vec![
|
example: "echo [1.5 2.3 -3.1] | math round",
|
||||||
UntaggedValue::int(2).into(),
|
result: Some(vec![
|
||||||
UntaggedValue::int(2).into(),
|
UntaggedValue::int(2).into(),
|
||||||
UntaggedValue::int(-3).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,
|
||||||
|
registry: &CommandRegistry,
|
||||||
|
) -> Result<OutputStream, ShellError> {
|
||||||
|
let (Arguments { precision }, input) = args.process(®istry).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 {
|
fn round_big_int(val: BigInt) -> Value {
|
||||||
UntaggedValue::int(val).into()
|
UntaggedValue::int(val).into()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn round_big_decimal(val: BigDecimal) -> Value {
|
fn round_big_decimal(val: BigDecimal, precision: i64) -> Value {
|
||||||
let (rounded, _) = val.round(0).as_bigint_and_exponent();
|
if precision > 0 {
|
||||||
UntaggedValue::int(rounded).into()
|
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 {
|
fn round_default(_: UntaggedValue) -> Value {
|
||||||
@ -71,6 +96,7 @@ fn round_default(_: UntaggedValue) -> Value {
|
|||||||
))
|
))
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::ShellError;
|
use super::ShellError;
|
||||||
|
@ -7,7 +7,7 @@ use nu_source::{Tagged, TaggedItem};
|
|||||||
pub struct InputStream {
|
pub struct InputStream {
|
||||||
values: BoxStream<'static, Value>,
|
values: BoxStream<'static, Value>,
|
||||||
|
|
||||||
// Whether or not an empty stream was explicitly requeted via InputStream::empty
|
// Whether or not an empty stream was explicitly requested via InputStream::empty
|
||||||
empty: bool,
|
empty: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user