mirror of
https://github.com/nushell/nushell
synced 2024-12-26 04:53:09 +00:00
Make a calc
command (#1280)
This commit is contained in:
parent
ac5ad45783
commit
dc3370b103
7 changed files with 128 additions and 0 deletions
17
Cargo.lock
generated
17
Cargo.lock
generated
|
@ -1927,6 +1927,16 @@ dependencies = [
|
|||
"rustc_version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "meval"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f79496a5651c8d57cd033c5add8ca7ee4e3d5f7587a4777484640d9cb60392d9"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"nom 1.2.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.14"
|
||||
|
@ -2070,6 +2080,12 @@ version = "0.1.14"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "1.2.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5b8c256fd9471521bcb84c3cdba98921497f1a331cbc15b8030fc63b82050ce"
|
||||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "4.2.3"
|
||||
|
@ -2170,6 +2186,7 @@ dependencies = [
|
|||
"itertools 0.8.2",
|
||||
"language-reporting",
|
||||
"log",
|
||||
"meval",
|
||||
"natural",
|
||||
"nom 5.1.0",
|
||||
"nom-tracable",
|
||||
|
|
|
@ -123,6 +123,7 @@ termcolor = "1.1.0"
|
|||
natural = "0.3.0"
|
||||
parking_lot = "0.10.0"
|
||||
futures-timer = "1.0.2"
|
||||
meval = "0.2"
|
||||
|
||||
clipboard = {version = "0.5", optional = true }
|
||||
ptree = {version = "0.2" }
|
||||
|
|
|
@ -268,6 +268,7 @@ pub async fn cli() -> Result<(), Box<dyn Error>> {
|
|||
whole_stream_command(Save),
|
||||
per_item_command(Cpy),
|
||||
whole_stream_command(Date),
|
||||
per_item_command(Calc),
|
||||
per_item_command(Mkdir),
|
||||
per_item_command(Move),
|
||||
whole_stream_command(Version),
|
||||
|
|
|
@ -7,6 +7,7 @@ mod to_delimited_data;
|
|||
pub(crate) mod append;
|
||||
pub(crate) mod args;
|
||||
pub(crate) mod autoview;
|
||||
pub(crate) mod calc;
|
||||
pub(crate) mod cd;
|
||||
pub(crate) mod classified;
|
||||
pub(crate) mod clip;
|
||||
|
@ -107,6 +108,7 @@ pub(crate) use command::{
|
|||
};
|
||||
|
||||
pub(crate) use append::Append;
|
||||
pub(crate) use calc::Calc;
|
||||
pub(crate) use compact::Compact;
|
||||
pub(crate) use config::Config;
|
||||
pub(crate) use count::Count;
|
||||
|
|
57
src/commands/calc.rs
Normal file
57
src/commands/calc.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
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(
|
||||
"Calulation 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> {
|
||||
let num = meval::eval_str(math_expression);
|
||||
match num {
|
||||
Ok(num) => Ok(UntaggedValue::from(Primitive::from(num)).into_value(tag)),
|
||||
Err(error) => Err(error.to_string()),
|
||||
}
|
||||
}
|
49
tests/commands/calc.rs
Normal file
49
tests/commands/calc.rs
Normal file
|
@ -0,0 +1,49 @@
|
|||
use nu_test_support::{nu, pipeline};
|
||||
|
||||
#[test]
|
||||
fn calculates_two_plus_two() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"
|
||||
echo "2 + 2" | calc
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.contains("4.0"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn calculates_two_to_the_power_six() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"
|
||||
echo "2 ^ 6" | calc
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.contains("64.0"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn calculates_three_multiplied_by_five() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"
|
||||
echo "3 * 5" | calc
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.contains("15.0"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn calculates_twenty_four_divided_by_two() {
|
||||
let actual = nu!(
|
||||
cwd: ".", pipeline(
|
||||
r#"
|
||||
echo "24 / 2" | calc
|
||||
"#
|
||||
));
|
||||
|
||||
assert!(actual.contains("12.0"));
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
mod append;
|
||||
mod calc;
|
||||
mod cd;
|
||||
mod compact;
|
||||
mod cp;
|
||||
|
|
Loading…
Reference in a new issue