From 8d3a937413abbee6470d9d3f47a2b7d4f6ffa539 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20N=2E=20Robalino?= Date: Sat, 23 Nov 2019 18:53:50 -0500 Subject: [PATCH 1/3] Display raw debugging data (rust represetantion). --- src/commands/debug.rs | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/commands/debug.rs b/src/commands/debug.rs index f9639b7263..b31f65ca2e 100644 --- a/src/commands/debug.rs +++ b/src/commands/debug.rs @@ -4,7 +4,9 @@ use crate::prelude::*; pub struct Debug; #[derive(Deserialize)] -pub struct DebugArgs {} +pub struct DebugArgs { + raw: Tagged, +} impl WholeStreamCommand for Debug { fn name(&self) -> &str { @@ -12,7 +14,7 @@ impl WholeStreamCommand for Debug { } fn signature(&self) -> Signature { - Signature::build("debug") + Signature::build("debug").switch("raw", "print raw data") } fn usage(&self) -> &str { @@ -29,14 +31,19 @@ impl WholeStreamCommand for Debug { } fn debug_value( - _args: DebugArgs, + DebugArgs { raw }: DebugArgs, RunnableContext { mut input, .. }: RunnableContext, -) -> Result { +) -> Result { let stream = async_stream! { while let Some(row) = input.values.next().await { - yield ReturnSuccess::debug_value(row.clone()) + if let Tagged { item: true, .. } = raw { + println!("{:?}", row); + yield ReturnSuccess::value(row) + } else { + yield ReturnSuccess::debug_value(row.clone()) + } } }; - Ok(stream) + Ok(stream.to_output_stream()) } From 1a0b33989710b353c67332689ed6b054b48da164 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20N=2E=20Robalino?= Date: Sat, 23 Nov 2019 18:57:12 -0500 Subject: [PATCH 2/3] compact command introduced. --- README.md | 3 ++- src/cli.rs | 1 + src/commands.rs | 2 ++ src/commands/compact.rs | 53 +++++++++++++++++++++++++++++++++++++++++ src/commands/debug.rs | 2 +- src/data/base.rs | 11 +++++++++ tests/commands_test.rs | 48 +++++++++++++++++++++++++++++++++++++ 7 files changed, 118 insertions(+), 2 deletions(-) create mode 100644 src/commands/compact.rs diff --git a/README.md b/README.md index 733eff4403..75bfe7d56a 100644 --- a/README.md +++ b/README.md @@ -268,6 +268,7 @@ Nu adheres closely to a set of goals that make up its design philosophy. As feat | command | description | | ------------- | ------------- | | 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 | | 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 | @@ -286,7 +287,7 @@ Nu adheres closely to a set of goals that make up its design philosophy. As feat | reject ...columns | Remove the given columns from the table | | reverse | Reverses the table. | | skip amount | Skip a number of rows | -| skip-while condition | Skips rows while the condition matches. | +| skip-while condition | Skips rows while the condition matches | | split-by column | Creates a new table with the data from the inner tables splitted by the column given | | sort-by ...columns | Sort by the given columns | | str (column) | Apply string function. Optionally use the column of a table | diff --git a/src/cli.rs b/src/cli.rs index 153cd0abdc..0354b642e8 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -309,6 +309,7 @@ pub async fn cli() -> Result<(), Box> { per_item_command(Where), per_item_command(Echo), whole_stream_command(Config), + whole_stream_command(Compact), whole_stream_command(SkipWhile), per_item_command(Enter), per_item_command(Help), diff --git a/src/commands.rs b/src/commands.rs index 5c06be2a88..0d8c0c8986 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -11,6 +11,7 @@ pub(crate) mod cd; pub(crate) mod classified; pub(crate) mod clip; pub(crate) mod command; +pub(crate) mod compact; pub(crate) mod config; pub(crate) mod count; pub(crate) mod cp; @@ -98,6 +99,7 @@ pub(crate) use command::{ pub(crate) use append::Append; pub(crate) use classified::ClassifiedCommand; +pub(crate) use compact::Compact; pub(crate) use config::Config; pub(crate) use count::Count; pub(crate) use cp::Cpy; diff --git a/src/commands/compact.rs b/src/commands/compact.rs new file mode 100644 index 0000000000..be18b8ce42 --- /dev/null +++ b/src/commands/compact.rs @@ -0,0 +1,53 @@ +use crate::commands::WholeStreamCommand; +use crate::errors::ShellError; +use crate::parser::registry::{CommandRegistry, Signature}; +use crate::prelude::*; +use futures::stream::StreamExt; + +pub struct Compact; + +#[derive(Deserialize)] +pub struct CompactArgs { + rest: Vec>, +} + +impl WholeStreamCommand for Compact { + fn name(&self) -> &str { + "compact" + } + + fn signature(&self) -> Signature { + Signature::build("compact").rest(SyntaxShape::Any, "the columns to compact from the table") + } + + fn usage(&self) -> &str { + "Creates a table with non-empty rows" + } + + fn run( + &self, + args: CommandArgs, + registry: &CommandRegistry, + ) -> Result { + args.process(registry, compact)?.run() + } +} + +pub fn compact( + CompactArgs { rest: columns }: CompactArgs, + RunnableContext { input, .. }: RunnableContext, +) -> Result { + let objects = input.values.take_while(move |item| { + let keep = if columns.is_empty() { + item.is_some() + } else { + columns + .iter() + .all(|field| item.get_data(field).borrow().is_some()) + }; + + futures::future::ready(keep) + }); + + Ok(objects.from_input_stream()) +} diff --git a/src/commands/debug.rs b/src/commands/debug.rs index b31f65ca2e..eaa493588d 100644 --- a/src/commands/debug.rs +++ b/src/commands/debug.rs @@ -36,7 +36,7 @@ fn debug_value( ) -> Result { let stream = async_stream! { while let Some(row) = input.values.next().await { - if let Tagged { item: true, .. } = raw { + if let Tagged { item: true, .. } = raw { println!("{:?}", row); yield ReturnSuccess::value(row) } else { diff --git a/src/data/base.rs b/src/data/base.rs index 0579e7017e..49bfc2b6c4 100644 --- a/src/data/base.rs +++ b/src/data/base.rs @@ -497,6 +497,17 @@ impl Value { } } + pub(crate) fn is_some(&self) -> bool { + !self.is_none() + } + + pub(crate) fn is_none(&self) -> bool { + match self { + Value::Primitive(Primitive::Nothing) => true, + _ => false, + } + } + pub(crate) fn is_error(&self) -> bool { match self { Value::Error(_err) => true, diff --git a/tests/commands_test.rs b/tests/commands_test.rs index db0121a9c1..2569bd02e9 100644 --- a/tests/commands_test.rs +++ b/tests/commands_test.rs @@ -3,6 +3,54 @@ mod helpers; use helpers as h; use helpers::{Playground, Stub::*}; +#[test] +fn compact_rows_where_given_column_is_empty() { + Playground::setup("compact_test_1", |dirs, sandbox| { + sandbox.with_files(vec![FileWithContentToBeTrimmed( + "los_tres_amigos.json", + r#" + { + "amigos": [ + {"name": "Yehuda", "rusty_luck": 1}, + {"name": "Jonathan", "rusty_luck": 1}, + {"name": "Andres", "rusty_luck": 1}, + {"name":"GorbyPuff"} + ] + } + "#, + )]); + + let actual = nu!( + cwd: dirs.test(), h::pipeline( + r#" + open los_tres_amigos.json + | get amigos + | compact rusty_luck + | count + | echo $it + "# + )); + + assert_eq!(actual, "3"); + }); +} +#[test] +fn compact_empty_rows_by_default() { + Playground::setup("compact_test_2", |dirs, sandbox| { + let actual = nu!( + cwd: dirs.test(), h::pipeline( + r#" + echo "[1,2,3,14,null]" + | from-json + | compact + | count + | echo $it + "# + )); + + assert_eq!(actual, "4"); + }); +} #[test] fn group_by() { Playground::setup("group_by_test_1", |dirs, sandbox| { From bc2d65cd2ecffccf550ead70f2430fd7bda5a954 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20N=2E=20Robalino?= Date: Sat, 23 Nov 2019 19:07:12 -0500 Subject: [PATCH 3/3] Remove raw data debugging. --- src/commands/debug.rs | 19 ++++++------------- tests/commands_test.rs | 2 +- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/src/commands/debug.rs b/src/commands/debug.rs index eaa493588d..f9639b7263 100644 --- a/src/commands/debug.rs +++ b/src/commands/debug.rs @@ -4,9 +4,7 @@ use crate::prelude::*; pub struct Debug; #[derive(Deserialize)] -pub struct DebugArgs { - raw: Tagged, -} +pub struct DebugArgs {} impl WholeStreamCommand for Debug { fn name(&self) -> &str { @@ -14,7 +12,7 @@ impl WholeStreamCommand for Debug { } fn signature(&self) -> Signature { - Signature::build("debug").switch("raw", "print raw data") + Signature::build("debug") } fn usage(&self) -> &str { @@ -31,19 +29,14 @@ impl WholeStreamCommand for Debug { } fn debug_value( - DebugArgs { raw }: DebugArgs, + _args: DebugArgs, RunnableContext { mut input, .. }: RunnableContext, -) -> Result { +) -> Result { let stream = async_stream! { while let Some(row) = input.values.next().await { - if let Tagged { item: true, .. } = raw { - println!("{:?}", row); - yield ReturnSuccess::value(row) - } else { - yield ReturnSuccess::debug_value(row.clone()) - } + yield ReturnSuccess::debug_value(row.clone()) } }; - Ok(stream.to_output_stream()) + Ok(stream) } diff --git a/tests/commands_test.rs b/tests/commands_test.rs index 2569bd02e9..646cf57cb8 100644 --- a/tests/commands_test.rs +++ b/tests/commands_test.rs @@ -36,7 +36,7 @@ fn compact_rows_where_given_column_is_empty() { } #[test] fn compact_empty_rows_by_default() { - Playground::setup("compact_test_2", |dirs, sandbox| { + Playground::setup("compact_test_2", |dirs, _| { let actual = nu!( cwd: dirs.test(), h::pipeline( r#"