mirror of
https://github.com/nushell/nushell.git
synced 2024-11-25 01:43:47 +01:00
Make sum plugin as internal command. (#1501)
This commit is contained in:
parent
390deb4ff7
commit
21a543a901
12
Cargo.lock
generated
12
Cargo.lock
generated
@ -2264,7 +2264,6 @@ dependencies = [
|
||||
"nu_plugin_post",
|
||||
"nu_plugin_ps",
|
||||
"nu_plugin_str",
|
||||
"nu_plugin_sum",
|
||||
"nu_plugin_sys",
|
||||
"nu_plugin_textview",
|
||||
"nu_plugin_tree",
|
||||
@ -2642,17 +2641,6 @@ dependencies = [
|
||||
"regex",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nu_plugin_sum"
|
||||
version = "0.11.0"
|
||||
dependencies = [
|
||||
"nu-build",
|
||||
"nu-errors",
|
||||
"nu-plugin",
|
||||
"nu-protocol",
|
||||
"nu-source",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nu_plugin_sys"
|
||||
version = "0.11.0"
|
||||
|
@ -33,7 +33,6 @@ nu_plugin_match = { version = "0.11.0", path = "./crates/nu_plugin_match", optio
|
||||
nu_plugin_post = { version = "0.11.0", path = "./crates/nu_plugin_post", optional=true }
|
||||
nu_plugin_ps = { version = "0.11.0", path = "./crates/nu_plugin_ps", optional=true }
|
||||
nu_plugin_str = { version = "0.11.0", path = "./crates/nu_plugin_str", optional=true }
|
||||
nu_plugin_sum = { version = "0.11.0", path = "./crates/nu_plugin_sum", optional=true }
|
||||
nu_plugin_sys = { version = "0.11.0", path = "./crates/nu_plugin_sys", optional=true }
|
||||
nu_plugin_textview = { version = "0.11.0", path = "./crates/nu_plugin_textview", optional=true }
|
||||
nu_plugin_tree = { version = "0.11.0", path = "./crates/nu_plugin_tree", optional=true }
|
||||
@ -66,7 +65,7 @@ nu-build = { version = "0.11.0", path = "./crates/nu-build" }
|
||||
test-bins = []
|
||||
|
||||
default = ["sys", "ps", "textview", "inc", "str"]
|
||||
stable = ["default", "starship-prompt", "binaryview", "match", "tree", "average", "sum", "post", "fetch", "clipboard-cli"]
|
||||
stable = ["default", "starship-prompt", "binaryview", "match", "tree", "average", "post", "fetch", "clipboard-cli"]
|
||||
|
||||
# Default
|
||||
textview = ["crossterm", "syntect", "onig_sys", "url", "nu_plugin_textview"]
|
||||
@ -81,7 +80,6 @@ binaryview = ["nu_plugin_binaryview"]
|
||||
fetch = ["nu_plugin_fetch"]
|
||||
match = ["nu_plugin_match"]
|
||||
post = ["nu_plugin_post"]
|
||||
sum = ["nu_plugin_sum"]
|
||||
trace = ["nu-parser/trace"]
|
||||
tree = ["nu_plugin_tree"]
|
||||
|
||||
@ -167,11 +165,6 @@ name = "nu_plugin_stable_post"
|
||||
path = "src/plugins/nu_plugin_stable_post.rs"
|
||||
required-features = ["post"]
|
||||
|
||||
[[bin]]
|
||||
name = "nu_plugin_stable_sum"
|
||||
path = "src/plugins/nu_plugin_stable_sum.rs"
|
||||
required-features = ["sum"]
|
||||
|
||||
[[bin]]
|
||||
name = "nu_plugin_stable_tree"
|
||||
path = "src/plugins/nu_plugin_stable_tree.rs"
|
||||
|
@ -313,6 +313,7 @@ pub fn create_default_context(
|
||||
whole_stream_command(Pivot),
|
||||
// Data processing
|
||||
whole_stream_command(Histogram),
|
||||
whole_stream_command(Sum),
|
||||
// File format output
|
||||
whole_stream_command(ToBSON),
|
||||
whole_stream_command(ToCSV),
|
||||
|
@ -81,6 +81,7 @@ pub(crate) mod sort_by;
|
||||
pub(crate) mod split_by;
|
||||
pub(crate) mod split_column;
|
||||
pub(crate) mod split_row;
|
||||
pub(crate) mod sum;
|
||||
#[allow(unused)]
|
||||
pub(crate) mod t_sort_by;
|
||||
pub(crate) mod table;
|
||||
@ -186,6 +187,7 @@ pub(crate) use sort_by::SortBy;
|
||||
pub(crate) use split_by::SplitBy;
|
||||
pub(crate) use split_column::SplitColumn;
|
||||
pub(crate) use split_row::SplitRow;
|
||||
pub(crate) use sum::Sum;
|
||||
#[allow(unused_imports)]
|
||||
pub(crate) use t_sort_by::TSortBy;
|
||||
pub(crate) use table::Table;
|
||||
|
55
crates/nu-cli/src/commands/sum.rs
Normal file
55
crates/nu-cli/src/commands/sum.rs
Normal file
@ -0,0 +1,55 @@
|
||||
use crate::commands::WholeStreamCommand;
|
||||
use crate::prelude::*;
|
||||
use crate::utils::data_processing::{reducer_for, Reduce};
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{ReturnSuccess, ReturnValue, Signature, Value};
|
||||
use num_traits::identities::Zero;
|
||||
|
||||
pub struct Sum;
|
||||
|
||||
impl WholeStreamCommand for Sum {
|
||||
fn name(&self) -> &str {
|
||||
"sum"
|
||||
}
|
||||
|
||||
fn signature(&self) -> Signature {
|
||||
Signature::build("sum")
|
||||
}
|
||||
|
||||
fn usage(&self) -> &str {
|
||||
"Sums the values."
|
||||
}
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
args: CommandArgs,
|
||||
registry: &CommandRegistry,
|
||||
) -> Result<OutputStream, ShellError> {
|
||||
sum(RunnableContext {
|
||||
input: args.input,
|
||||
commands: registry.clone(),
|
||||
shell_manager: args.shell_manager,
|
||||
host: args.host,
|
||||
source: args.call_info.source,
|
||||
ctrl_c: args.ctrl_c,
|
||||
name: args.call_info.name_tag,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn sum(RunnableContext { mut input, .. }: RunnableContext) -> Result<OutputStream, ShellError> {
|
||||
let stream = async_stream! {
|
||||
let mut values = input.drain_vec().await;
|
||||
|
||||
let action = reducer_for(Reduce::Sum);
|
||||
|
||||
match action(Value::zero(), values) {
|
||||
Ok(total) => yield ReturnSuccess::value(total),
|
||||
Err(err) => yield Err(err),
|
||||
}
|
||||
};
|
||||
|
||||
let stream: BoxStream<'static, ReturnValue> = stream.boxed();
|
||||
|
||||
Ok(stream.to_output_stream())
|
||||
}
|
@ -1,10 +1,11 @@
|
||||
use crate::data::value::compare_values;
|
||||
use crate::data::TaggedListBuilder;
|
||||
use chrono::{DateTime, NaiveDate, Utc};
|
||||
use nu_errors::ShellError;
|
||||
use nu_parser::CompareOperator;
|
||||
use nu_protocol::{Primitive, TaggedDictBuilder, UntaggedValue, Value};
|
||||
use nu_source::{SpannedItem, Tag, Tagged, TaggedItem};
|
||||
use nu_value_ext::{get_data_by_key, ValueExt};
|
||||
use num_bigint::BigInt;
|
||||
use num_traits::Zero;
|
||||
|
||||
pub fn columns_sorted(
|
||||
@ -196,44 +197,31 @@ pub fn evaluate(
|
||||
Ok(results)
|
||||
}
|
||||
|
||||
fn sum(data: Vec<Value>) -> Result<Value, ShellError> {
|
||||
let total = data
|
||||
pub fn sum(data: Vec<Value>) -> Result<Value, ShellError> {
|
||||
Ok(data
|
||||
.into_iter()
|
||||
.fold(Zero::zero(), |acc: BigInt, value| match value {
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Int(n)),
|
||||
..
|
||||
} => acc + n,
|
||||
_ => acc,
|
||||
});
|
||||
|
||||
Ok(UntaggedValue::int(total).into_untagged_value())
|
||||
.fold(Value::zero(), |acc: Value, value| acc + value))
|
||||
}
|
||||
|
||||
fn formula(
|
||||
acc_begin: BigInt,
|
||||
calculator: Box<dyn Fn(Vec<Value>) -> Result<Value, ShellError> + 'static>,
|
||||
) -> Box<dyn Fn(BigInt, Vec<Value>) -> Result<Value, ShellError> + 'static> {
|
||||
acc_begin: Value,
|
||||
calculator: Box<dyn Fn(Vec<Value>) -> Result<Value, ShellError> + Send + Sync + 'static>,
|
||||
) -> Box<dyn Fn(Value, Vec<Value>) -> Result<Value, ShellError> + Send + Sync + 'static> {
|
||||
Box::new(move |acc, datax| -> Result<Value, ShellError> {
|
||||
let result = acc * acc_begin.clone();
|
||||
|
||||
if let Ok(Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Int(computed)),
|
||||
..
|
||||
}) = calculator(datax)
|
||||
{
|
||||
return Ok(UntaggedValue::int(result + computed).into_untagged_value());
|
||||
match calculator(datax) {
|
||||
Ok(total) => Ok(result + total),
|
||||
Err(reason) => Err(reason),
|
||||
}
|
||||
|
||||
Ok(UntaggedValue::int(0).into_untagged_value())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn reducer_for(
|
||||
command: Reduce,
|
||||
) -> Box<dyn Fn(BigInt, Vec<Value>) -> Result<Value, ShellError> + 'static> {
|
||||
) -> Box<dyn Fn(Value, Vec<Value>) -> Result<Value, ShellError> + Send + Sync + 'static> {
|
||||
match command {
|
||||
Reduce::Sum | Reduce::Default => Box::new(formula(Zero::zero(), Box::new(sum))),
|
||||
Reduce::Sum | Reduce::Default => Box::new(formula(Value::zero(), Box::new(sum))),
|
||||
}
|
||||
}
|
||||
|
||||
@ -262,7 +250,7 @@ pub fn reduce(
|
||||
let datasets: Vec<_> = datasets
|
||||
.iter()
|
||||
.map(|subsets| {
|
||||
let acc: BigInt = Zero::zero();
|
||||
let acc = Value::zero();
|
||||
match subsets {
|
||||
Value {
|
||||
value: UntaggedValue::Table(data),
|
||||
@ -318,37 +306,48 @@ pub fn map_max(
|
||||
value: UntaggedValue::Table(datasets),
|
||||
..
|
||||
} => {
|
||||
let datasets: Vec<_> = datasets
|
||||
let datasets: Vec<Value> = datasets
|
||||
.iter()
|
||||
.map(|subsets| match subsets {
|
||||
Value {
|
||||
value: UntaggedValue::Table(data),
|
||||
..
|
||||
} => {
|
||||
let data: BigInt =
|
||||
data.iter().fold(Zero::zero(), |acc, value| match value {
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Int(n)),
|
||||
..
|
||||
} if *n > acc => n.clone(),
|
||||
_ => acc,
|
||||
});
|
||||
UntaggedValue::int(data).into_value(&tag)
|
||||
}
|
||||
} => data.iter().fold(Value::zero(), |acc, value| {
|
||||
let left = &value.value;
|
||||
let right = &acc.value;
|
||||
|
||||
if let Ok(is_greater_than) =
|
||||
compare_values(CompareOperator::GreaterThan, left, right)
|
||||
{
|
||||
if is_greater_than {
|
||||
value.clone()
|
||||
} else {
|
||||
acc
|
||||
}
|
||||
} else {
|
||||
acc
|
||||
}
|
||||
}),
|
||||
_ => UntaggedValue::int(0).into_value(&tag),
|
||||
})
|
||||
.collect();
|
||||
|
||||
let datasets: BigInt = datasets
|
||||
.iter()
|
||||
.fold(Zero::zero(), |max, value| match value {
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Int(n)),
|
||||
..
|
||||
} if *n > max => n.clone(),
|
||||
_ => max,
|
||||
});
|
||||
UntaggedValue::int(datasets).into_value(&tag)
|
||||
datasets.into_iter().fold(Value::zero(), |max, value| {
|
||||
let left = &value.value;
|
||||
let right = &max.value;
|
||||
|
||||
if let Ok(is_greater_than) =
|
||||
compare_values(CompareOperator::GreaterThan, left, right)
|
||||
{
|
||||
if is_greater_than {
|
||||
value
|
||||
} else {
|
||||
max
|
||||
}
|
||||
} else {
|
||||
max
|
||||
}
|
||||
})
|
||||
}
|
||||
_ => UntaggedValue::int(-1).into_value(&tag),
|
||||
};
|
||||
@ -573,7 +572,7 @@ mod tests {
|
||||
|
||||
let action = reducer_for(Reduce::Sum);
|
||||
|
||||
assert_eq!(action(Zero::zero(), subject)?, int(3));
|
||||
assert_eq!(action(Value::zero(), subject)?, int(3));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -29,6 +29,7 @@ mod save;
|
||||
mod sort_by;
|
||||
mod split_by;
|
||||
mod split_column;
|
||||
mod sum;
|
||||
mod touch;
|
||||
mod uniq;
|
||||
mod where_;
|
||||
|
30
crates/nu-cli/tests/commands/sum.rs
Normal file
30
crates/nu-cli/tests/commands/sum.rs
Normal file
@ -0,0 +1,30 @@
|
||||
use nu_test_support::fs::Stub::FileWithContentToBeTrimmed;
|
||||
use nu_test_support::playground::Playground;
|
||||
use nu_test_support::{nu, pipeline};
|
||||
|
||||
#[test]
|
||||
fn all() {
|
||||
Playground::setup("sum_test_1", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"meals.csv",
|
||||
r#"
|
||||
description,calories
|
||||
"1 large egg",90
|
||||
"1 cup white rice",250
|
||||
"1 tablespoon fish oil",108
|
||||
"#,
|
||||
)]);
|
||||
|
||||
let actual = nu!(
|
||||
cwd: dirs.test(), pipeline(
|
||||
r#"
|
||||
open meals.csv
|
||||
| get calories
|
||||
| sum
|
||||
| echo $it
|
||||
"#
|
||||
));
|
||||
|
||||
assert_eq!(actual, "448");
|
||||
})
|
||||
}
|
@ -4,7 +4,7 @@ use nu_test_support::{nu, pipeline};
|
||||
|
||||
#[test]
|
||||
fn wrap_rows_into_a_row() {
|
||||
Playground::setup("embed_test_1", |dirs, sandbox| {
|
||||
Playground::setup("wrap_test_1", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"los_tres_caballeros.txt",
|
||||
r#"
|
||||
@ -34,7 +34,7 @@ fn wrap_rows_into_a_row() {
|
||||
|
||||
#[test]
|
||||
fn wrap_rows_into_a_table() {
|
||||
Playground::setup("embed_test_2", |dirs, sandbox| {
|
||||
Playground::setup("wrap_test_2", |dirs, sandbox| {
|
||||
sandbox.with_files(vec![FileWithContentToBeTrimmed(
|
||||
"los_tres_caballeros.txt",
|
||||
r#"
|
||||
|
@ -379,6 +379,60 @@ impl From<ShellError> for UntaggedValue {
|
||||
}
|
||||
}
|
||||
|
||||
impl num_traits::Zero for Value {
|
||||
fn zero() -> Self {
|
||||
Value {
|
||||
value: UntaggedValue::Primitive(Primitive::zero()),
|
||||
tag: Tag::unknown(),
|
||||
}
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> bool {
|
||||
match &self.value {
|
||||
UntaggedValue::Primitive(primitive) => primitive.is_zero(),
|
||||
UntaggedValue::Row(row) => row.entries.is_empty(),
|
||||
UntaggedValue::Table(rows) => rows.is_empty(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul for Value {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: Self) -> Self {
|
||||
let tag = self.tag.clone();
|
||||
|
||||
match (&*self, &*rhs) {
|
||||
(UntaggedValue::Primitive(left), UntaggedValue::Primitive(right)) => {
|
||||
let left = left.clone();
|
||||
let right = right.clone();
|
||||
|
||||
UntaggedValue::from(left.mul(right)).into_value(tag)
|
||||
}
|
||||
(_, _) => unimplemented!("Internal error: can't multiply non-primitives."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Add for Value {
|
||||
type Output = Self;
|
||||
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
let tag = self.tag.clone();
|
||||
|
||||
match (&*self, &*rhs) {
|
||||
(UntaggedValue::Primitive(left), UntaggedValue::Primitive(right)) => {
|
||||
let left = left.clone();
|
||||
let right = right.clone();
|
||||
|
||||
UntaggedValue::from(left.add(right)).into_value(tag)
|
||||
}
|
||||
(_, _) => unimplemented!("Internal error: can't add non-primitives."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn merge_descriptors(values: &[Value]) -> Vec<String> {
|
||||
let mut ret: Vec<String> = vec![];
|
||||
let value_column = "<value>".to_string();
|
||||
|
@ -8,6 +8,7 @@ use nu_errors::{ExpectedRange, ShellError};
|
||||
use nu_source::{PrettyDebug, Span, SpannedItem};
|
||||
use num_bigint::BigInt;
|
||||
use num_traits::cast::{FromPrimitive, ToPrimitive};
|
||||
use num_traits::identities::Zero;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
|
||||
@ -75,6 +76,82 @@ impl Primitive {
|
||||
}
|
||||
}
|
||||
|
||||
impl num_traits::Zero for Primitive {
|
||||
fn zero() -> Self {
|
||||
Primitive::Int(BigInt::zero())
|
||||
}
|
||||
|
||||
fn is_zero(&self) -> bool {
|
||||
match self {
|
||||
Primitive::Int(int) => int.is_zero(),
|
||||
Primitive::Decimal(decimal) => decimal.is_zero(),
|
||||
Primitive::Bytes(size) => size.is_zero(),
|
||||
Primitive::Nothing => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Add for Primitive {
|
||||
type Output = Primitive;
|
||||
|
||||
fn add(self, rhs: Self) -> Self {
|
||||
match (self, rhs) {
|
||||
(Primitive::Int(left), Primitive::Int(right)) => Primitive::Int(left + right),
|
||||
(Primitive::Int(left), Primitive::Decimal(right)) => {
|
||||
Primitive::Decimal(BigDecimal::from(left) + right)
|
||||
}
|
||||
(Primitive::Decimal(left), Primitive::Decimal(right)) => {
|
||||
Primitive::Decimal(left + right)
|
||||
}
|
||||
(Primitive::Decimal(left), Primitive::Int(right)) => {
|
||||
Primitive::Decimal(left + BigDecimal::from(right))
|
||||
}
|
||||
(Primitive::Bytes(left), right) => match right {
|
||||
Primitive::Bytes(right) => Primitive::Bytes(left + right),
|
||||
Primitive::Int(right) => {
|
||||
Primitive::Bytes(left + right.to_u64().unwrap_or_else(|| 0 as u64))
|
||||
}
|
||||
Primitive::Decimal(right) => {
|
||||
Primitive::Bytes(left + right.to_u64().unwrap_or_else(|| 0 as u64))
|
||||
}
|
||||
_ => Primitive::Bytes(left),
|
||||
},
|
||||
(left, Primitive::Bytes(right)) => match left {
|
||||
Primitive::Bytes(left) => Primitive::Bytes(left + right),
|
||||
Primitive::Int(left) => {
|
||||
Primitive::Bytes(left.to_u64().unwrap_or_else(|| 0 as u64) + right)
|
||||
}
|
||||
Primitive::Decimal(left) => {
|
||||
Primitive::Bytes(left.to_u64().unwrap_or_else(|| 0 as u64) + right)
|
||||
}
|
||||
_ => Primitive::Bytes(right),
|
||||
},
|
||||
_ => Primitive::zero(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::ops::Mul for Primitive {
|
||||
type Output = Self;
|
||||
|
||||
fn mul(self, rhs: Self) -> Self {
|
||||
match (self, rhs) {
|
||||
(Primitive::Int(left), Primitive::Int(right)) => Primitive::Int(left * right),
|
||||
(Primitive::Int(left), Primitive::Decimal(right)) => {
|
||||
Primitive::Decimal(BigDecimal::from(left) * right)
|
||||
}
|
||||
(Primitive::Decimal(left), Primitive::Decimal(right)) => {
|
||||
Primitive::Decimal(left * right)
|
||||
}
|
||||
(Primitive::Decimal(left), Primitive::Int(right)) => {
|
||||
Primitive::Decimal(left * BigDecimal::from(right))
|
||||
}
|
||||
_ => unimplemented!("Internal error: can't multiply incompatible primitives."),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BigDecimal> for Primitive {
|
||||
/// Helper to convert from decimals to a Primitive value
|
||||
fn from(decimal: BigDecimal) -> Primitive {
|
||||
@ -82,6 +159,13 @@ impl From<BigDecimal> for Primitive {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<BigInt> for Primitive {
|
||||
/// Helper to convert from integers to a Primitive value
|
||||
fn from(int: BigInt) -> Primitive {
|
||||
Primitive::Int(int)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<f64> for Primitive {
|
||||
/// Helper to convert from 64-bit float to a Primitive value
|
||||
fn from(float: f64) -> Primitive {
|
||||
|
@ -1,19 +0,0 @@
|
||||
[package]
|
||||
name = "nu_plugin_sum"
|
||||
version = "0.11.0"
|
||||
authors = ["Yehuda Katz <wycats@gmail.com>", "Jonathan Turner <jonathan.d.turner@gmail.com>", "Andrés N. Robalino <andres@androbtech.com>"]
|
||||
edition = "2018"
|
||||
description = "A simple summation plugin for Nushell"
|
||||
license = "MIT"
|
||||
|
||||
[lib]
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
nu-plugin = { path = "../nu-plugin", version = "0.11.0" }
|
||||
nu-protocol = { path = "../nu-protocol", version = "0.11.0" }
|
||||
nu-source = { path = "../nu-source", version = "0.11.0" }
|
||||
nu-errors = { path = "../nu-errors", version = "0.11.0" }
|
||||
|
||||
[build-dependencies]
|
||||
nu-build = { version = "0.11.0", path = "../nu-build" }
|
@ -1,3 +0,0 @@
|
||||
fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
nu_build::build()
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
mod nu;
|
||||
mod sum;
|
||||
|
||||
pub use sum::Sum;
|
@ -1,6 +0,0 @@
|
||||
use nu_plugin::serve_plugin;
|
||||
use nu_plugin_sum::Sum;
|
||||
|
||||
fn main() {
|
||||
serve_plugin(&mut Sum::new());
|
||||
}
|
@ -1,29 +0,0 @@
|
||||
use nu_errors::ShellError;
|
||||
use nu_plugin::Plugin;
|
||||
use nu_protocol::{CallInfo, ReturnSuccess, ReturnValue, Signature, Value};
|
||||
|
||||
use crate::Sum;
|
||||
|
||||
impl Plugin for Sum {
|
||||
fn config(&mut self) -> Result<Signature, ShellError> {
|
||||
Ok(Signature::build("sum")
|
||||
.desc("Sum a column of values.")
|
||||
.filter())
|
||||
}
|
||||
|
||||
fn begin_filter(&mut self, _: CallInfo) -> Result<Vec<ReturnValue>, ShellError> {
|
||||
Ok(vec![])
|
||||
}
|
||||
|
||||
fn filter(&mut self, input: Value) -> Result<Vec<ReturnValue>, ShellError> {
|
||||
self.sum(input)?;
|
||||
Ok(vec![])
|
||||
}
|
||||
|
||||
fn end_filter(&mut self) -> Result<Vec<ReturnValue>, ShellError> {
|
||||
match self.total {
|
||||
None => Ok(vec![]),
|
||||
Some(ref v) => Ok(vec![ReturnSuccess::value(v.clone())]),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
use nu_errors::ShellError;
|
||||
use nu_protocol::{Primitive, UntaggedValue, Value};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Sum {
|
||||
pub total: Option<Value>,
|
||||
}
|
||||
|
||||
impl Sum {
|
||||
pub fn new() -> Sum {
|
||||
Sum { total: None }
|
||||
}
|
||||
|
||||
pub fn sum(&mut self, value: Value) -> Result<(), ShellError> {
|
||||
match &value.value {
|
||||
UntaggedValue::Primitive(Primitive::Nothing) => Ok(()),
|
||||
UntaggedValue::Primitive(Primitive::Int(i)) => {
|
||||
match &self.total {
|
||||
Some(Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Int(j)),
|
||||
tag,
|
||||
}) => {
|
||||
//TODO: handle overflow
|
||||
self.total = Some(UntaggedValue::int(i + j).into_value(tag));
|
||||
Ok(())
|
||||
}
|
||||
None => {
|
||||
self.total = Some(value.clone());
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(ShellError::labeled_error(
|
||||
"Could not sum non-integer or unrelated types",
|
||||
"source",
|
||||
value.tag,
|
||||
)),
|
||||
}
|
||||
}
|
||||
UntaggedValue::Primitive(Primitive::Bytes(b)) => {
|
||||
match &self.total {
|
||||
Some(Value {
|
||||
value: UntaggedValue::Primitive(Primitive::Bytes(j)),
|
||||
tag,
|
||||
}) => {
|
||||
//TODO: handle overflow
|
||||
self.total = Some(UntaggedValue::bytes(b + j).into_value(tag));
|
||||
Ok(())
|
||||
}
|
||||
None => {
|
||||
self.total = Some(value);
|
||||
Ok(())
|
||||
}
|
||||
_ => Err(ShellError::labeled_error(
|
||||
"Could not sum non-integer or unrelated types",
|
||||
"source",
|
||||
value.tag,
|
||||
)),
|
||||
}
|
||||
}
|
||||
x => Err(ShellError::labeled_error(
|
||||
format!("Unrecognized type in stream: {:?}", x),
|
||||
"source",
|
||||
value.tag,
|
||||
)),
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
use nu_plugin::serve_plugin;
|
||||
use nu_plugin_sum::Sum;
|
||||
|
||||
fn main() {
|
||||
serve_plugin(&mut Sum::new());
|
||||
}
|
Loading…
Reference in New Issue
Block a user