From 83ddf0ebe24d4ce917e8ce75a473305ab45602ec Mon Sep 17 00:00:00 2001 From: Reilly Wood <26268125+rgwood@users.noreply.github.com> Date: Fri, 31 Mar 2023 16:40:19 -0700 Subject: [PATCH] Make optional cell paths work with `reject` (#8697) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This PR makes `?` work with `reject`. For example: ```bash > {} | reject foo Error: nu::shell::column_not_found × Cannot find column ╭─[entry #2:1:1] 1 │ {} | reject foo · ───┬── ─┬─ · │ ╰── cannot find column 'foo' · ╰── value originates here ╰──── > {} | reject foo? ╭──────────────╮ │ empty record │ ╰──────────────╯ ``` This was prompted by [a user question](https://discord.com/channels/601130461678272522/614593951969574961/1091466428546306078). I would like to get this in for 0.78, I think it's low-risk and I want the `?` feature to be as polished as possible for its debut. --- crates/nu-command/tests/commands/reject.rs | 21 +++++++++++++++++++ crates/nu-protocol/src/value/mod.rs | 24 ++++++++++++++-------- 2 files changed, 37 insertions(+), 8 deletions(-) diff --git a/crates/nu-command/tests/commands/reject.rs b/crates/nu-command/tests/commands/reject.rs index d393016c8a..9d290a0981 100644 --- a/crates/nu-command/tests/commands/reject.rs +++ b/crates/nu-command/tests/commands/reject.rs @@ -147,3 +147,24 @@ fn reject_large_vec_with_two_identical_elements() { assert!(actual.out.contains("100")); assert!(actual.out.contains('2')); } + +#[test] +fn reject_optional_column() { + let actual = nu!("{} | reject foo? | to nuon"); + assert_eq!(actual.out, "{}"); + + let actual = nu!("[{}] | reject foo? | to nuon"); + assert_eq!(actual.out, "[{}]"); + + let actual = nu!("[{} {foo: 2}] | reject foo? | to nuon"); + assert_eq!(actual.out, "[{}, {}]"); + + let actual = nu!("[{foo: 1} {foo: 2}] | reject foo? | to nuon"); + assert_eq!(actual.out, "[{}, {}]"); +} + +#[test] +fn reject_optional_row() { + let actual = nu!("[{foo: 'bar'}] | reject 3? | to nuon"); + assert_eq!(actual.out, "[[foo]; [bar]]"); +} diff --git a/crates/nu-protocol/src/value/mod.rs b/crates/nu-protocol/src/value/mod.rs index 87501f3f94..81a92430ce 100644 --- a/crates/nu-protocol/src/value/mod.rs +++ b/crates/nu-protocol/src/value/mod.rs @@ -1208,7 +1208,7 @@ impl Value { PathMember::String { val: col_name, span, - .. + optional, } => match self { Value::List { vals, .. } => { for val in vals.iter_mut() { @@ -1230,7 +1230,7 @@ impl Value { true } }); - if !found { + if !found && !optional { return Err(ShellError::CantFindColumn { col_name: col_name.to_string(), span: *span, @@ -1262,7 +1262,7 @@ impl Value { found = true; } } - if !found { + if !found && !optional { return Err(ShellError::CantFindColumn { col_name: col_name.to_string(), span: *span, @@ -1278,12 +1278,16 @@ impl Value { }), }, PathMember::Int { - val: row_num, span, .. + val: row_num, + span, + optional, } => match self { Value::List { vals, .. } => { if vals.get_mut(*row_num).is_some() { vals.remove(*row_num); Ok(()) + } else if *optional { + Ok(()) } else if vals.is_empty() { Err(ShellError::AccessEmptyContent { span: *span }) } else { @@ -1306,7 +1310,7 @@ impl Value { PathMember::String { val: col_name, span, - .. + optional, } => match self { Value::List { vals, .. } => { for val in vals.iter_mut() { @@ -1323,7 +1327,7 @@ impl Value { col.1.remove_data_at_cell_path(&cell_path[1..])? } } - if !found { + if !found && !optional { return Err(ShellError::CantFindColumn { col_name: col_name.to_string(), span: *span, @@ -1356,7 +1360,7 @@ impl Value { col.1.remove_data_at_cell_path(&cell_path[1..])? } } - if !found { + if !found && !optional { return Err(ShellError::CantFindColumn { col_name: col_name.to_string(), span: *span, @@ -1372,11 +1376,15 @@ impl Value { }), }, PathMember::Int { - val: row_num, span, .. + val: row_num, + span, + optional, } => match self { Value::List { vals, .. } => { if let Some(v) = vals.get_mut(*row_num) { v.remove_data_at_cell_path(&cell_path[1..]) + } else if *optional { + Ok(()) } else if vals.is_empty() { Err(ShellError::AccessEmptyContent { span: *span }) } else {