Add new operators has and not-has (#14841)

# Description
This PR add 2 new operators, `has` and `not-has`. They are basically
`in` and `not-in` with the order of operands swapped.

Motivation for this was the awkward way of searching for rows that
contain an item using `where`

```nushell
[[name, children]; [foo, [a, b, c]], [bar [d, e, f]]]
| where ("e" in $it.children)
```
vs
```nushell
[[name, children]; [foo, [a, b, c]], [bar [d, e, f]]]
| where children has "e"
``` 

# User-Facing Changes
Added `has` and `not-has` operators, mirroring `in` and `not-in`.

# Tests + Formatting

- 🟢 toolkit fmt
- 🟢 toolkit clippy
- 🟢 toolkit test
- 🟢 toolkit test stdlib

# After Submitting
This commit is contained in:
Bahex
2025-01-17 15:20:00 +03:00
committed by GitHub
parent 0587308684
commit 089c5221cc
9 changed files with 97 additions and 41 deletions

View File

@ -17,6 +17,8 @@ pub enum Comparison {
NotRegexMatch,
In,
NotIn,
Has,
NotHas,
StartsWith,
EndsWith,
}
@ -90,6 +92,8 @@ impl Operator {
| Self::Comparison(Comparison::NotEqual)
| Self::Comparison(Comparison::In)
| Self::Comparison(Comparison::NotIn)
| Self::Comparison(Comparison::Has)
| Self::Comparison(Comparison::NotHas)
| Self::Math(Math::Concat) => 80,
Self::Bits(Bits::BitAnd) => 75,
Self::Bits(Bits::BitXor) => 70,
@ -123,6 +127,8 @@ impl Display for Operator {
Operator::Comparison(Comparison::EndsWith) => write!(f, "ends-with"),
Operator::Comparison(Comparison::In) => write!(f, "in"),
Operator::Comparison(Comparison::NotIn) => write!(f, "not-in"),
Operator::Comparison(Comparison::Has) => write!(f, "has"),
Operator::Comparison(Comparison::NotHas) => write!(f, "not-has"),
Operator::Math(Math::Plus) => write!(f, "+"),
Operator::Math(Math::Concat) => write!(f, "++"),
Operator::Math(Math::Minus) => write!(f, "-"),

View File

@ -256,6 +256,8 @@ pub trait Eval {
Comparison::NotEqual => lhs.ne(op_span, &rhs, expr_span),
Comparison::In => lhs.r#in(op_span, &rhs, expr_span),
Comparison::NotIn => lhs.not_in(op_span, &rhs, expr_span),
Comparison::Has => lhs.has(op_span, &rhs, expr_span),
Comparison::NotHas => lhs.not_has(op_span, &rhs, expr_span),
Comparison::StartsWith => lhs.starts_with(op_span, &rhs, expr_span),
Comparison::EndsWith => lhs.ends_with(op_span, &rhs, expr_span),
Comparison::RegexMatch => {

View File

@ -3540,6 +3540,14 @@ impl Value {
}
}
pub fn has(&self, op: Span, rhs: &Value, span: Span) -> Result<Value, ShellError> {
rhs.r#in(op, self, span)
}
pub fn not_has(&self, op: Span, rhs: &Value, span: Span) -> Result<Value, ShellError> {
rhs.r#not_in(op, self, span)
}
pub fn regex_match(
&self,
engine_state: &EngineState,