diff --git a/crates/nu-command/src/filters/compact.rs b/crates/nu-command/src/filters/compact.rs index 865c3bb9f..46ca6237d 100644 --- a/crates/nu-command/src/filters/compact.rs +++ b/crates/nu-command/src/filters/compact.rs @@ -27,6 +27,11 @@ impl Command for Compact { Type::List(Box::new(Type::Any)), ), ]) + .switch( + "empty", + "also compact empty items like \"\", {}, and []", + Some('e'), + ) .rest( "columns", SyntaxShape::Any, @@ -46,18 +51,19 @@ impl Command for Compact { call: &Call, input: PipelineData, ) -> Result { - compact(engine_state, stack, call, input) + let empty = call.has_flag("empty"); + compact(engine_state, stack, call, input, empty) } fn examples(&self) -> Vec { vec![ Example { - description: "Filter out all records where 'Hello' is null (returns nothing)", + description: "Filter out all records where 'Hello' is null", example: r#"[["Hello" "World"]; [null 3]] | compact Hello"#, result: Some(Value::test_list(vec![])), }, Example { - description: "Filter out all records where 'World' is null (Returns the table)", + description: "Filter out all records where 'World' is null", example: r#"[["Hello" "World"]; [null 3]] | compact World"#, result: Some(Value::test_list(vec![Value::test_record(record! { "Hello" => Value::nothing(Span::test_data()), @@ -65,13 +71,24 @@ impl Command for Compact { })])), }, Example { - description: "Filter out all instances of nothing from a list (Returns [1,2])", + description: "Filter out all instances of null from a list", example: r#"[1, null, 2] | compact"#, result: Some(Value::test_list(vec![ Value::test_int(1), Value::test_int(2), ])), }, + Example { + description: "Filter out all instances of null and empty items from a list", + example: r#"[1, null, 2, "", 3, [], 4, {}, 5] | compact --empty"#, + result: Some(Value::test_list(vec![ + Value::test_int(1), + Value::test_int(2), + Value::test_int(3), + Value::test_int(4), + Value::test_int(5), + ])), + }, ] } } @@ -81,6 +98,7 @@ pub fn compact( stack: &mut Stack, call: &Call, input: PipelineData, + compact_empties: bool, ) -> Result { let columns: Vec = call.rest(engine_state, stack, 0)?; let metadata = input.metadata(); @@ -90,7 +108,7 @@ pub fn compact( match item { // Nothing is filtered out Value::Nothing { .. } => false, - Value::Record { .. } => { + Value::Record { val, .. } => { for column in columns.iter() { match item.get_data_by_key(column) { None => return false, @@ -98,12 +116,35 @@ pub fn compact( if let Value::Nothing { .. } = x { return false; } + if compact_empties { + if let Value::String { val, .. } = x { + if val.is_empty() { + return false; + } + } + } } } } + + if compact_empties && val.is_empty() { + return false; + } // No defined columns contained Nothing true } + Value::List { vals, .. } => { + if compact_empties && vals.is_empty() { + return false; + } + true + } + Value::String { val, .. } => { + if compact_empties && val.is_empty() { + return false; + } + true + } // Any non-Nothing, non-record should be kept _ => true, }