diff --git a/Cargo.lock b/Cargo.lock index 921d2f55e..da325eb8b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -809,6 +809,15 @@ version = "1.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb1f6b1ce1c140482ea30ddd3335fc0024ac7ee112895426e0a629a6c20adfe3" +[[package]] +name = "eml-parser" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9e30d14e24cd200f2351837a02feacf8f043410f2a56441868c93ef33f90239" +dependencies = [ + "regex", +] + [[package]] name = "encode_unicode" version = "0.3.6" @@ -2128,6 +2137,7 @@ dependencies = [ "derive-new", "dirs 2.0.2", "dunce", + "eml-parser", "filesize", "futures 0.3.4", "futures-util", diff --git a/crates/nu-cli/src/evaluate/operator.rs b/crates/nu-cli/src/evaluate/operator.rs index 1134f260c..291c40b4f 100644 --- a/crates/nu-cli/src/evaluate/operator.rs +++ b/crates/nu-cli/src/evaluate/operator.rs @@ -26,6 +26,7 @@ pub fn apply_operator( Operator::Multiply => value::compute_values(op, left, right), Operator::Divide => value::compute_values(op, left, right), Operator::In => table_contains(left, right).map(UntaggedValue::boolean), + Operator::NotIn => table_contains(left, right).map(|x| UntaggedValue::boolean(!x)), Operator::And => match (left.as_bool(), right.as_bool()) { (Ok(left), Ok(right)) => Ok(UntaggedValue::boolean(left && right)), _ => Err((left.type_name(), right.type_name())), diff --git a/crates/nu-cli/tests/commands/where_.rs b/crates/nu-cli/tests/commands/where_.rs index 01ccb9705..764a972da 100644 --- a/crates/nu-cli/tests/commands/where_.rs +++ b/crates/nu-cli/tests/commands/where_.rs @@ -20,6 +20,26 @@ fn filters_with_nothing_comparison() { assert_eq!(actual, "7"); } +#[test] +fn where_in_table() { + let actual = nu!( + cwd: "tests/fixtures/formats", + r#"echo '[{"name": "foo", "size": 3}, {"name": "foo", "size": 2}, {"name": "bar", "size": 4}]' | from-json | where name in: ["foo"] | get size | sum | echo $it"# + ); + + assert_eq!(actual, "5"); +} + +#[test] +fn where_not_in_table() { + let actual = nu!( + cwd: "tests/fixtures/formats", + r#"echo '[{"name": "foo", "size": 3}, {"name": "foo", "size": 2}, {"name": "bar", "size": 4}]' | from-json | where name not-in: ["foo"] | get size | sum | echo $it"# + ); + + assert_eq!(actual, "4"); +} + #[test] fn explicit_block_condition() { let actual = nu!( diff --git a/crates/nu-parser/src/parse.rs b/crates/nu-parser/src/parse.rs index 3003716fb..79dfb919f 100644 --- a/crates/nu-parser/src/parse.rs +++ b/crates/nu-parser/src/parse.rs @@ -247,6 +247,8 @@ fn parse_operator(lite_arg: &Spanned) -> (SpannedExpression, Option 80, + | Operator::In + | Operator::NotIn => 80, Operator::And => 50, Operator::Or => 40, // TODO: should we have And and Or be different precedence? } @@ -589,6 +590,7 @@ pub enum Operator { Multiply, Divide, In, + NotIn, And, Or, }