diff --git a/crates/nu-command/src/filters/get.rs b/crates/nu-command/src/filters/get.rs index fd7f52675c..42bd3f29e1 100644 --- a/crates/nu-command/src/filters/get.rs +++ b/crates/nu-command/src/filters/get.rs @@ -28,7 +28,7 @@ impl Command for Get { .rest("rest", SyntaxShape::CellPath, "additional cell paths") .switch( "ignore-errors", - "return nothing if path can't be found", + "when there are empty cells, instead of erroring out, replace them with nothing", Some('i'), ) .switch( diff --git a/crates/nu-command/src/filters/select.rs b/crates/nu-command/src/filters/select.rs index 7efa0fa6c4..05c40a45df 100644 --- a/crates/nu-command/src/filters/select.rs +++ b/crates/nu-command/src/filters/select.rs @@ -17,6 +17,11 @@ impl Command for Select { // FIXME: also add support for --skip fn signature(&self) -> Signature { Signature::build("select") + .switch( + "ignore-errors", + "when a column has empty cells, instead of erroring out, replace them with nothing", + Some('i'), + ) .rest( "rest", SyntaxShape::CellPath, @@ -42,8 +47,9 @@ impl Command for Select { ) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> { let columns: Vec<CellPath> = call.rest(engine_state, stack, 0)?; let span = call.head; + let ignore_empty = call.has_flag("ignore-errors"); - select(engine_state, span, columns, input) + select(engine_state, span, columns, input, ignore_empty) } fn examples(&self) -> Vec<Example> { @@ -67,6 +73,7 @@ fn select( span: Span, columns: Vec<CellPath>, input: PipelineData, + ignore_empty: bool, ) -> Result<PipelineData, ShellError> { let mut rows = vec![]; @@ -121,6 +128,7 @@ fn select( .., ) => { let mut output = vec![]; + let mut columns_with_value = Vec::new(); for input_val in input_vals { if !columns.is_empty() { @@ -128,10 +136,25 @@ fn select( let mut vals = vec![]; for path in &columns { //FIXME: improve implementation to not clone - let fetcher = input_val.clone().follow_cell_path(&path.members, false)?; + if ignore_empty { + let fetcher = input_val.clone().follow_cell_path(&path.members, false); - cols.push(path.into_string().replace('.', "_")); - vals.push(fetcher); + cols.push(path.into_string().replace('.', "_")); + if let Ok(fetcher) = fetcher { + vals.push(fetcher); + if !columns_with_value.contains(&path) { + columns_with_value.push(path); + } + } else { + vals.push(Value::nothing(span)); + } + } else { + let fetcher = + input_val.clone().follow_cell_path(&path.members, false)?; + + cols.push(path.into_string().replace('.', "_")); + vals.push(fetcher); + } } output.push(Value::Record { cols, vals, span }) diff --git a/crates/nu-command/tests/commands/select.rs b/crates/nu-command/tests/commands/select.rs index ac8eed2522..76c7e190ae 100644 --- a/crates/nu-command/tests/commands/select.rs +++ b/crates/nu-command/tests/commands/select.rs @@ -159,3 +159,27 @@ fn selects_many_rows() { assert_eq!(actual.out, "2"); }); } + +#[test] +fn select_ignores_errors_succesfully1() { + let actual = nu!( + cwd: ".", pipeline( + r#" + [{a: 1, b: 2} {a: 3, b: 5} {a: 3}] | select -i b + "# + )); + + assert!(actual.err.is_empty()); +} + +#[test] +fn select_ignores_errors_succesfully2() { + let actual = nu!( + cwd: ".", pipeline( + r#" + [{a: 1} {a: 2} {a: 3}] | select -i b + "# + )); + + assert!(actual.err.is_empty()); +}