forked from extern/nushell
b2c5af457e
This improves incremental build time when working on what was previously the root package. For example, previously all plugins would be rebuilt with a change to `src/commands/classified/external.rs`, but now only `nu-cli` will have to be rebuilt (and anything that depends on it).
64 lines
1.7 KiB
Rust
64 lines
1.7 KiB
Rust
use crate::commands::PerItemCommand;
|
|
use crate::prelude::*;
|
|
use nu_errors::ShellError;
|
|
use nu_protocol::{CallInfo, Primitive, ReturnSuccess, UntaggedValue, Value};
|
|
|
|
pub struct Calc;
|
|
|
|
impl PerItemCommand for Calc {
|
|
fn name(&self) -> &str {
|
|
"calc"
|
|
}
|
|
|
|
fn usage(&self) -> &str {
|
|
"Parse a math expression into a number"
|
|
}
|
|
|
|
fn run(
|
|
&self,
|
|
_call_info: &CallInfo,
|
|
_registry: &CommandRegistry,
|
|
raw_args: &RawCommandArgs,
|
|
input: Value,
|
|
) -> Result<OutputStream, ShellError> {
|
|
calc(input, raw_args)
|
|
}
|
|
}
|
|
|
|
fn calc(input: Value, args: &RawCommandArgs) -> Result<OutputStream, ShellError> {
|
|
let name_span = &args.call_info.name_tag.span;
|
|
|
|
let output = if let Ok(string) = input.as_string() {
|
|
match parse(&string, &input.tag) {
|
|
Ok(value) => ReturnSuccess::value(value),
|
|
Err(err) => Err(ShellError::labeled_error(
|
|
"Calculation error",
|
|
err,
|
|
&input.tag.span,
|
|
)),
|
|
}
|
|
} else {
|
|
Err(ShellError::labeled_error(
|
|
"Expected a string from pipeline",
|
|
"requires string input",
|
|
name_span,
|
|
))
|
|
};
|
|
|
|
Ok(vec![output].into())
|
|
}
|
|
|
|
pub fn parse(math_expression: &str, tag: impl Into<Tag>) -> Result<Value, String> {
|
|
use std::f64;
|
|
let num = meval::eval_str(math_expression);
|
|
match num {
|
|
Ok(num) => {
|
|
if num == f64::INFINITY || num == f64::NEG_INFINITY {
|
|
return Err(String::from("cannot represent result"));
|
|
}
|
|
Ok(UntaggedValue::from(Primitive::from(num)).into_value(tag))
|
|
}
|
|
Err(error) => Err(error.to_string()),
|
|
}
|
|
}
|