From a74145961e8a8674b30ae973babb5bdf61616a54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20N=2E=20Robalino?= Date: Sun, 24 Nov 2019 01:25:41 -0500 Subject: [PATCH 1/3] Always check the row's columns. --- src/commands/compact.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/commands/compact.rs b/src/commands/compact.rs index be18b8ce42..ab0c96ba41 100644 --- a/src/commands/compact.rs +++ b/src/commands/compact.rs @@ -41,9 +41,15 @@ pub fn compact( let keep = if columns.is_empty() { item.is_some() } else { - columns - .iter() - .all(|field| item.get_data(field).borrow().is_some()) + match item { + Tagged { + item: Value::Row(ref r), + .. + } => columns + .iter() + .all(|field| r.get_data(field).borrow().is_some()), + _ => false, + } }; futures::future::ready(keep) From 1c830b5c95e984f4fd9adc853457c01c4479f0eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20N=2E=20Robalino?= Date: Sun, 24 Nov 2019 04:20:08 -0500 Subject: [PATCH 2/3] default command introduced. --- README.md | 1 + src/cli.rs | 1 + src/commands.rs | 2 ++ src/commands/default.rs | 72 +++++++++++++++++++++++++++++++++++++++++ tests/commands_test.rs | 32 ++++++++++++++++++ 5 files changed, 108 insertions(+) create mode 100644 src/commands/default.rs diff --git a/README.md b/README.md index 75bfe7d56a..5baa3e5ce0 100644 --- a/README.md +++ b/README.md @@ -270,6 +270,7 @@ Nu adheres closely to a set of goals that make up its design philosophy. As feat | append row-data | Append a row to the end of the table | | compact ...columns | Remove rows where given columns are empty | | count | Show the total number of rows | +| default column row-data | Sets a default row's column if missing | | edit column-or-column-path value | Edit an existing column to have a new value | | embed column | Creates a new table of one column with the given name, and places the current table inside of it | | first amount | Show only the first number of rows | diff --git a/src/cli.rs b/src/cli.rs index 0354b642e8..64d562f97e 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -310,6 +310,7 @@ pub async fn cli() -> Result<(), Box> { per_item_command(Echo), whole_stream_command(Config), whole_stream_command(Compact), + whole_stream_command(Default), whole_stream_command(SkipWhile), per_item_command(Enter), per_item_command(Help), diff --git a/src/commands.rs b/src/commands.rs index 0d8c0c8986..705deb1d56 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -17,6 +17,7 @@ pub(crate) mod count; pub(crate) mod cp; pub(crate) mod date; pub(crate) mod debug; +pub(crate) mod default; pub(crate) mod echo; pub(crate) mod enter; pub(crate) mod env; @@ -105,6 +106,7 @@ pub(crate) use count::Count; pub(crate) use cp::Cpy; pub(crate) use date::Date; pub(crate) use debug::Debug; +pub(crate) use default::Default; pub(crate) use echo::Echo; pub(crate) use enter::Enter; pub(crate) use env::Env; diff --git a/src/commands/default.rs b/src/commands/default.rs new file mode 100644 index 0000000000..099fd32e0d --- /dev/null +++ b/src/commands/default.rs @@ -0,0 +1,72 @@ +use crate::commands::WholeStreamCommand; +use crate::errors::ShellError; +use crate::parser::CommandRegistry; +use crate::prelude::*; + +#[derive(Deserialize)] +struct DefaultArgs { + column: Tagged, + value: Tagged, +} + +pub struct Default; + +impl WholeStreamCommand for Default { + fn name(&self) -> &str { + "default" + } + + fn signature(&self) -> Signature { + Signature::build("default") + .required("column name", SyntaxShape::String, "the name of the column") + .required( + "column value", + SyntaxShape::Any, + "the value of the column to default", + ) + } + + fn usage(&self) -> &str { + "Sets a default row's column if missing." + } + + fn run( + &self, + args: CommandArgs, + registry: &CommandRegistry, + ) -> Result { + args.process(registry, default)?.run() + } +} + +fn default( + DefaultArgs { column, value }: DefaultArgs, + RunnableContext { input, .. }: RunnableContext, +) -> Result { + let stream = input + .values + .map(move |item| { + let mut result = VecDeque::new(); + + let should_add = match item { + Tagged { + item: Value::Row(ref r), + .. + } => r.get_data(&column.item).borrow().is_none(), + _ => false, + }; + + if should_add { + match item.insert_data_at_path(&column.item, value.item.clone()) { + Some(new_value) => result.push_back(ReturnSuccess::value(new_value)), + None => {} + } + } else { + result.push_back(ReturnSuccess::value(item)); + } + result + }) + .flatten(); + + Ok(stream.to_output_stream()) +} diff --git a/tests/commands_test.rs b/tests/commands_test.rs index 646cf57cb8..4da12d5c80 100644 --- a/tests/commands_test.rs +++ b/tests/commands_test.rs @@ -3,6 +3,38 @@ mod helpers; use helpers as h; use helpers::{Playground, Stub::*}; +#[test] +fn default() { + Playground::setup("default_test_1", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "los_tres_amigos.json", + r#" + { + "amigos": [ + {"name": "Yehuda"}, + {"name": "Jonathan", "rusty_luck": 0}, + {"name": "Andres", "rusty_luck": 0}, + {"name":"GorbyPuff"} + ] + } + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), h::pipeline( + r#" + open los_tres_amigos.json + | get amigos + | default rusty_luck 1 + | get rusty_luck + | sum + | echo $it + "# + )); + + assert_eq!(actual, "2"); + }); +} #[test] fn compact_rows_where_given_column_is_empty() { Playground::setup("compact_test_1", |dirs, sandbox| { From 06857fbc527de647c4e66d238e4eea493f2712df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20N=2E=20Robalino?= Date: Sun, 24 Nov 2019 04:21:35 -0500 Subject: [PATCH 3/3] Take all rows having the column present. --- src/commands/compact.rs | 2 +- src/commands/default.rs | 2 +- tests/commands_test.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commands/compact.rs b/src/commands/compact.rs index ab0c96ba41..4660e88adc 100644 --- a/src/commands/compact.rs +++ b/src/commands/compact.rs @@ -37,7 +37,7 @@ pub fn compact( CompactArgs { rest: columns }: CompactArgs, RunnableContext { input, .. }: RunnableContext, ) -> Result { - let objects = input.values.take_while(move |item| { + let objects = input.values.filter(move |item| { let keep = if columns.is_empty() { item.is_some() } else { diff --git a/src/commands/default.rs b/src/commands/default.rs index 099fd32e0d..52d33e463c 100644 --- a/src/commands/default.rs +++ b/src/commands/default.rs @@ -59,7 +59,7 @@ fn default( if should_add { match item.insert_data_at_path(&column.item, value.item.clone()) { Some(new_value) => result.push_back(ReturnSuccess::value(new_value)), - None => {} + None => result.push_back(ReturnSuccess::value(item)), } } else { result.push_back(ReturnSuccess::value(item)); diff --git a/tests/commands_test.rs b/tests/commands_test.rs index 4da12d5c80..59621539db 100644 --- a/tests/commands_test.rs +++ b/tests/commands_test.rs @@ -4,7 +4,7 @@ use helpers as h; use helpers::{Playground, Stub::*}; #[test] -fn default() { +fn default_row_data_if_column_missing() { Playground::setup("default_test_1", |dirs, sandbox| { sandbox.with_files(vec![FileWithContentToBeTrimmed( "los_tres_amigos.json",