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] 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| {