diff --git a/crates/nu-command/src/filters/where_.rs b/crates/nu-command/src/filters/where_.rs index cf40639172..9c61caa9e5 100644 --- a/crates/nu-command/src/filters/where_.rs +++ b/crates/nu-command/src/filters/where_.rs @@ -10,13 +10,21 @@ impl Command for Where { } fn description(&self) -> &str { - "Filter values based on a row condition." + "Filter values of an input list based on a condition." } fn extra_description(&self) -> &str { - r#"This command works similar to 'filter' but allows extra shorthands for working with -tables, known as "row conditions". On the other hand, reading the condition from a variable is -not supported."# + r#"A condition is evaluated for each element of the input, and only elements which meet the condition are included in the output. + +A condition can be either a "row condition" or a closure. A row condition is a special short-hand syntax to simplify field access. +Each element of the input can be accessed through the $it variable. + +On the left hand side of a row condition, any field name is automatically expanded to use $it. +For example, where type == dir is equivalent to where $it.type == dir. This expansion does not happen when passing a subexpression or closure to where. + +When using a closure, the element is passed as an argument and as pipeline input to the closure. + +`where` supports closure literals, but not closures stored in a variable. To filter using a closure stored in a variable, use the `filter` command."# } fn command_type(&self) -> CommandType { @@ -34,9 +42,12 @@ not supported."# (Type::Range, Type::Any), ]) .required( - "row_condition", - SyntaxShape::RowCondition, - "Filter condition.", + "condition", + SyntaxShape::OneOf(vec![ + SyntaxShape::RowCondition, + SyntaxShape::Closure(Some(vec![SyntaxShape::Any])), + ]), + "Filter row condition or closure.", ) .allow_variants_without_examples(true) .category(Category::Filters) @@ -85,11 +96,9 @@ not supported."# )), }, Example { - description: "Filter items of a list according to a condition", - example: "[1 2] | where {|x| $x > 1}", - result: Some(Value::test_list( - vec![Value::test_int(2)], - )), + description: "List only the files in the current directory", + example: "ls | where type == file", + result: None, }, Example { description: "List all files in the current directory with sizes greater than 2kb", @@ -97,13 +106,8 @@ not supported."# result: None, }, Example { - description: "List only the files in the current directory", - example: "ls | where type == file", - result: None, - }, - Example { - description: "List all files with names that contain \"Car\"", - example: "ls | where name =~ \"Car\"", + description: r#"List all files with names that contain "Car""#, + example: r#"ls | where name =~ "Car""#, result: None, }, Example { @@ -111,18 +115,32 @@ not supported."# example: "ls | where modified >= (date now) - 2wk", result: None, }, + Example { + description: "Filter items of a list with a row condition", + example: "[1 2 3 4 5] | where $it > 2", + result: Some(Value::test_list( + vec![Value::test_int(3), Value::test_int(4), Value::test_int(5)], + )), + }, + Example { + description: "Filter items of a list with a closure", + example: "[1 2 3 4 5] | where {|x| $x > 2 }", + result: Some(Value::test_list( + vec![Value::test_int(3), Value::test_int(4), Value::test_int(5)], + )), + }, Example { description: "Find files whose filenames don't begin with the correct sequential number", - example: "ls | where type == file | sort-by name --natural | enumerate | where {|e| $e.item.name !~ $'^($e.index + 1)' } | each {|| get item }", + example: "ls | where type == file | sort-by name --natural | enumerate | where {|e| $e.item.name !~ $'^($e.index + 1)' } | get item", result: None, }, Example { - description: r#"Find case-insensitively files called "readme", without an explicit closure"#, + description: r#"Find case-insensitively files called "readme", with a subexpression"#, example: "ls | where ($it.name | str downcase) =~ readme", result: None, }, Example { - description: "same as above but with regex only", + description: r#"Find case-insensitively files called "readme", with regex only"#, example: "ls | where name =~ '(?i)readme'", result: None, }