From 540f0fd3942b3ab9e4953ce3e6a3037826887cc0 Mon Sep 17 00:00:00 2001 From: NotTheDr01ds <32344964+NotTheDr01ds@users.noreply.github.com> Date: Sat, 1 Mar 2025 14:13:52 -0500 Subject: [PATCH] Add `--empty` flag to `default` to handle empty values --- crates/nu-command/src/filters/default.rs | 20 +++++- crates/nu-command/tests/commands/default.rs | 74 ++++++++++++++++++++- 2 files changed, 88 insertions(+), 6 deletions(-) diff --git a/crates/nu-command/src/filters/default.rs b/crates/nu-command/src/filters/default.rs index 6e5610f1be..579f992bf9 100644 --- a/crates/nu-command/src/filters/default.rs +++ b/crates/nu-command/src/filters/default.rs @@ -23,6 +23,11 @@ impl Command for Default { SyntaxShape::String, "The name of the column.", ) + .switch( + "empty", + "also compact empty items like \"\", {}, and []", + Some('e'), + ) .category(Category::Filters) } @@ -37,7 +42,8 @@ impl Command for Default { call: &Call, input: PipelineData, ) -> Result { - default(engine_state, stack, call, input) + let empty = call.has_flag(engine_state, stack, "empty")?; + default(engine_state, stack, call, input, empty) } fn examples(&self) -> Vec { @@ -89,6 +95,7 @@ fn default( stack: &mut Stack, call: &Call, input: PipelineData, + default_when_empty: bool, ) -> Result { let metadata = input.metadata(); let value: Value = call.req(engine_state, stack, 0)?; @@ -104,7 +111,9 @@ fn default( } => { let record = record.to_mut(); if let Some(val) = record.get_mut(&column.item) { - if matches!(val, Value::Nothing { .. }) { + if matches!(val, Value::Nothing { .. }) + || (default_when_empty && val.is_empty()) + { *val = value.clone(); } } else { @@ -118,7 +127,12 @@ fn default( engine_state.signals(), ) .map(|x| x.set_metadata(metadata)) - } else if input.is_nothing() { + } else if input.is_nothing() + || (default_when_empty + && (matches!(input, PipelineData::Value(Value::String { ref val, .. }, _) if val.is_empty()) + || matches!(input, PipelineData::Value(Value::Record { ref val, .. }, _) if val.is_empty()) + || matches!(input, PipelineData::Value(Value::List { ref vals, .. }, _) if vals.is_empty()))) + { Ok(value.into_pipeline_data()) } else { Ok(input) diff --git a/crates/nu-command/tests/commands/default.rs b/crates/nu-command/tests/commands/default.rs index 6ecd14960a..1669aea4d1 100644 --- a/crates/nu-command/tests/commands/default.rs +++ b/crates/nu-command/tests/commands/default.rs @@ -5,10 +5,13 @@ fn adds_row_data_if_column_missing() { let sample = r#" { "amigos": [ - {"name": "Yehuda"}, + {"name": "Yehuda"}, {"name": "JT", "rusty_luck": 0}, - {"name": "Andres", "rusty_luck": 0}, - {"name":"GorbyPuff"} + {"name": "Andres", "rusty_luck": 0}, + {"name": "Michael", "rusty_luck": []}, + {"name": "Darren", "rusty_luck": {}}, + {"name": "Stefan", "rusty_luck": ""}, + {"name": "GorbyPuff"} ] } "#; @@ -44,3 +47,68 @@ fn replaces_null() { let actual = nu!(r#"null | default 1"#); assert_eq!(actual.out, "1"); } + +#[test] +fn adds_row_data_if_column_missing_or_empty() { + let sample = r#" + { + "amigos": [ + {"name": "Yehuda"}, + {"name": "JT", "rusty_luck": 0}, + {"name": "Andres", "rusty_luck": 0}, + {"name": "Michael", "rusty_luck": []}, + {"name": "Darren", "rusty_luck": {}}, + {"name": "Stefan", "rusty_luck": ""}, + {"name": "GorbyPuff"} + ] + } + "#; + + let actual = nu!(pipeline(&format!( + " + {sample} + | get amigos + | default -e 1 rusty_luck + | where rusty_luck == 1 + | length + " + ))); + + assert_eq!(actual.out, "5"); +} + +#[test] +fn replace_empty_string() { + let actual = nu!(r#"'' | default -e foo"#); + assert_eq!(actual.out, "foo"); +} + +#[test] +fn do_not_replace_empty_string() { + let actual = nu!(r#"'' | default 1"#); + assert_eq!(actual.out, ""); +} + +#[test] +fn replace_empty_list() { + let actual = nu!(r#"[] | default -e foo"#); + assert_eq!(actual.out, "foo"); +} + +#[test] +fn do_not_replace_empty_list() { + let actual = nu!(r#"[] | default 1 | length"#); + assert_eq!(actual.out, "0"); +} + +#[test] +fn replace_empty_record() { + let actual = nu!(r#"{} | default -e foo"#); + assert_eq!(actual.out, "foo"); +} + +#[test] +fn do_not_replace_empty_record() { + let actual = nu!(r#"{} | default {a:5} | columns | length"#); + assert_eq!(actual.out, "0"); +}