mirror of
https://github.com/nushell/nushell.git
synced 2024-11-22 08:23:24 +01:00
Add support for real comparison operators
This commit is contained in:
parent
52716d0c24
commit
76c295995d
@ -15,16 +15,21 @@ impl crate::Command for Where {
|
|||||||
let field: Result<String, _> = args.args[0].as_string();
|
let field: Result<String, _> = args.args[0].as_string();
|
||||||
let field = field?;
|
let field = field?;
|
||||||
|
|
||||||
let op: Result<String, _> = args.args[1].as_string();
|
match args.args[1] {
|
||||||
let op = op?;
|
Value::Primitive(Primitive::Operator(ref operator)) => {
|
||||||
|
|
||||||
let objects = args
|
let objects = args
|
||||||
.input
|
.input
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|item| find(&item, &field, &op, &args.args[2]))
|
.filter(|item| find(&item, &field, operator, &args.args[2]))
|
||||||
.map(|item| ReturnValue::Value(item.copy()))
|
.map(|item| ReturnValue::Value(item.copy()))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(objects)
|
Ok(objects)
|
||||||
}
|
}
|
||||||
|
ref x => {
|
||||||
|
println!("{:?}", x);
|
||||||
|
Err(ShellError::string("expected a comparison operator"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ use chrono::{DateTime, Utc};
|
|||||||
use chrono_humanize::Humanize;
|
use chrono_humanize::Humanize;
|
||||||
use ordered_float::OrderedFloat;
|
use ordered_float::OrderedFloat;
|
||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
|
use crate::parser::parse::Operator;
|
||||||
|
|
||||||
type OF64 = OrderedFloat<f64>;
|
type OF64 = OrderedFloat<f64>;
|
||||||
|
|
||||||
@ -18,6 +19,7 @@ pub enum Primitive {
|
|||||||
String(String),
|
String(String),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
Date(DateTime<Utc>),
|
Date(DateTime<Utc>),
|
||||||
|
Operator(Operator),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Primitive {
|
impl Primitive {
|
||||||
@ -48,6 +50,7 @@ impl Primitive {
|
|||||||
(false, Some(_)) => format!(""),
|
(false, Some(_)) => format!(""),
|
||||||
},
|
},
|
||||||
Primitive::Date(d) => format!("{}", d.humanize()),
|
Primitive::Date(d) => format!("{}", d.humanize()),
|
||||||
|
Primitive::Operator(o) => o.print()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -224,57 +227,57 @@ crate fn reject(obj: &Value, fields: &[String]) -> crate::object::Dictionary {
|
|||||||
out
|
out
|
||||||
}
|
}
|
||||||
|
|
||||||
crate fn find(obj: &Value, field: &str, op: &str, rhs: &Value) -> bool {
|
crate fn find(obj: &Value, field: &str, op: &Operator, rhs: &Value) -> bool {
|
||||||
let descs = obj.data_descriptors();
|
let descs = obj.data_descriptors();
|
||||||
match descs.iter().find(|d| d.name == *field) {
|
match descs.iter().find(|d| d.name == *field) {
|
||||||
None => false,
|
None => false,
|
||||||
Some(desc) => {
|
Some(desc) => {
|
||||||
let v = obj.get_data(desc).borrow().copy();
|
let v = obj.get_data(desc).borrow().copy();
|
||||||
//println!("'{:?}' '{}' '{:?}'", v, op, rhs);
|
//println!("'{:?}' '{:?}' '{:?}'", v, op, rhs);
|
||||||
|
|
||||||
match v {
|
match v {
|
||||||
Value::Primitive(Primitive::Boolean(b)) => match (op, rhs) {
|
Value::Primitive(Primitive::Boolean(b)) => match (op, rhs) {
|
||||||
("-eq", Value::Primitive(Primitive::Boolean(b2))) => b == *b2,
|
(Operator::Equal, Value::Primitive(Primitive::Boolean(b2))) => b == *b2,
|
||||||
("-ne", Value::Primitive(Primitive::Boolean(b2))) => b != *b2,
|
(Operator::NotEqual, Value::Primitive(Primitive::Boolean(b2))) => b != *b2,
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
Value::Primitive(Primitive::Bytes(i)) => match (op, rhs) {
|
Value::Primitive(Primitive::Bytes(i)) => match (op, rhs) {
|
||||||
("-lt", Value::Primitive(Primitive::Int(i2))) => i < (*i2 as u128),
|
(Operator::LessThan, Value::Primitive(Primitive::Int(i2))) => i < (*i2 as u128),
|
||||||
("-gt", Value::Primitive(Primitive::Int(i2))) => i > (*i2 as u128),
|
(Operator::GreaterThan, Value::Primitive(Primitive::Int(i2))) => i > (*i2 as u128),
|
||||||
("-le", Value::Primitive(Primitive::Int(i2))) => i <= (*i2 as u128),
|
(Operator::LessThanOrEqual, Value::Primitive(Primitive::Int(i2))) => i <= (*i2 as u128),
|
||||||
("-ge", Value::Primitive(Primitive::Int(i2))) => i >= (*i2 as u128),
|
(Operator::GreaterThanOrEqual, Value::Primitive(Primitive::Int(i2))) => i >= (*i2 as u128),
|
||||||
("-eq", Value::Primitive(Primitive::Int(i2))) => i == (*i2 as u128),
|
(Operator::Equal, Value::Primitive(Primitive::Int(i2))) => i == (*i2 as u128),
|
||||||
("-ne", Value::Primitive(Primitive::Int(i2))) => i != (*i2 as u128),
|
(Operator::NotEqual, Value::Primitive(Primitive::Int(i2))) => i != (*i2 as u128),
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
Value::Primitive(Primitive::Int(i)) => match (op, rhs) {
|
Value::Primitive(Primitive::Int(i)) => match (op, rhs) {
|
||||||
("-lt", Value::Primitive(Primitive::Int(i2))) => i < *i2,
|
(Operator::LessThan, Value::Primitive(Primitive::Int(i2))) => i < *i2,
|
||||||
("-gt", Value::Primitive(Primitive::Int(i2))) => i > *i2,
|
(Operator::GreaterThan, Value::Primitive(Primitive::Int(i2))) => i > *i2,
|
||||||
("-le", Value::Primitive(Primitive::Int(i2))) => i <= *i2,
|
(Operator::LessThanOrEqual, Value::Primitive(Primitive::Int(i2))) => i <= *i2,
|
||||||
("-ge", Value::Primitive(Primitive::Int(i2))) => i >= *i2,
|
(Operator::GreaterThanOrEqual, Value::Primitive(Primitive::Int(i2))) => i >= *i2,
|
||||||
("-eq", Value::Primitive(Primitive::Int(i2))) => i == *i2,
|
(Operator::Equal, Value::Primitive(Primitive::Int(i2))) => i == *i2,
|
||||||
("-ne", Value::Primitive(Primitive::Int(i2))) => i != *i2,
|
(Operator::NotEqual, Value::Primitive(Primitive::Int(i2))) => i != *i2,
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
Value::Primitive(Primitive::Float(i)) => match (op, rhs) {
|
Value::Primitive(Primitive::Float(i)) => match (op, rhs) {
|
||||||
("-lt", Value::Primitive(Primitive::Float(i2))) => i < *i2,
|
(Operator::LessThan, Value::Primitive(Primitive::Float(i2))) => i < *i2,
|
||||||
("-gt", Value::Primitive(Primitive::Float(i2))) => i > *i2,
|
(Operator::GreaterThan, Value::Primitive(Primitive::Float(i2))) => i > *i2,
|
||||||
("-le", Value::Primitive(Primitive::Float(i2))) => i <= *i2,
|
(Operator::LessThanOrEqual, Value::Primitive(Primitive::Float(i2))) => i <= *i2,
|
||||||
("-ge", Value::Primitive(Primitive::Float(i2))) => i >= *i2,
|
(Operator::GreaterThanOrEqual, Value::Primitive(Primitive::Float(i2))) => i >= *i2,
|
||||||
("-eq", Value::Primitive(Primitive::Float(i2))) => i == *i2,
|
(Operator::Equal, Value::Primitive(Primitive::Float(i2))) => i == *i2,
|
||||||
("-ne", Value::Primitive(Primitive::Float(i2))) => i != *i2,
|
(Operator::NotEqual, Value::Primitive(Primitive::Float(i2))) => i != *i2,
|
||||||
("-lt", Value::Primitive(Primitive::Int(i2))) => (i.into_inner()) < *i2 as f64,
|
(Operator::LessThan, Value::Primitive(Primitive::Int(i2))) => (i.into_inner()) < *i2 as f64,
|
||||||
("-gt", Value::Primitive(Primitive::Int(i2))) => i.into_inner() > *i2 as f64,
|
(Operator::GreaterThan, Value::Primitive(Primitive::Int(i2))) => i.into_inner() > *i2 as f64,
|
||||||
("-le", Value::Primitive(Primitive::Int(i2))) => i.into_inner() <= *i2 as f64,
|
(Operator::LessThanOrEqual, Value::Primitive(Primitive::Int(i2))) => i.into_inner() <= *i2 as f64,
|
||||||
("-ge", Value::Primitive(Primitive::Int(i2))) => i.into_inner() >= *i2 as f64,
|
(Operator::GreaterThanOrEqual, Value::Primitive(Primitive::Int(i2))) => i.into_inner() >= *i2 as f64,
|
||||||
("-eq", Value::Primitive(Primitive::Int(i2))) => i.into_inner() == *i2 as f64,
|
(Operator::Equal, Value::Primitive(Primitive::Int(i2))) => i.into_inner() == *i2 as f64,
|
||||||
("-ne", Value::Primitive(Primitive::Int(i2))) => i.into_inner() != *i2 as f64,
|
(Operator::NotEqual, Value::Primitive(Primitive::Int(i2))) => i.into_inner() != *i2 as f64,
|
||||||
|
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
Value::Primitive(Primitive::String(s)) => match (op, rhs) {
|
Value::Primitive(Primitive::String(s)) => match (op, rhs) {
|
||||||
("-eq", Value::Primitive(Primitive::String(s2))) => s == *s2,
|
(Operator::Equal, Value::Primitive(Primitive::String(s2))) => s == *s2,
|
||||||
("-ne", Value::Primitive(Primitive::String(s2))) => s != *s2,
|
(Operator::NotEqual, Value::Primitive(Primitive::String(s2))) => s != *s2,
|
||||||
_ => false,
|
_ => false,
|
||||||
},
|
},
|
||||||
_ => false,
|
_ => false,
|
||||||
|
@ -14,6 +14,45 @@ pub enum Item {
|
|||||||
Bare(String),
|
Bare(String),
|
||||||
Int(i64),
|
Int(i64),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
|
Operator(Operator),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||||
|
pub enum Operator {
|
||||||
|
Equal,
|
||||||
|
NotEqual,
|
||||||
|
LessThan,
|
||||||
|
GreaterThan,
|
||||||
|
LessThanOrEqual,
|
||||||
|
GreaterThanOrEqual,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Operator {
|
||||||
|
pub fn print(&self) -> String {
|
||||||
|
match *self {
|
||||||
|
Operator::Equal => "==".to_string(),
|
||||||
|
Operator::NotEqual => "!=".to_string(),
|
||||||
|
Operator::LessThan => "<".to_string(),
|
||||||
|
Operator::GreaterThan => ">".to_string(),
|
||||||
|
Operator::LessThanOrEqual => "<=".to_string(),
|
||||||
|
Operator::GreaterThanOrEqual => ">=".to_string(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for Operator {
|
||||||
|
type Err = ();
|
||||||
|
fn from_str(input: &str) -> Result<Self, <Self as std::str::FromStr>::Err> {
|
||||||
|
match input {
|
||||||
|
"==" => Ok(Operator::Equal),
|
||||||
|
"!=" => Ok(Operator::NotEqual),
|
||||||
|
"<" => Ok(Operator::LessThan),
|
||||||
|
">" => Ok(Operator::GreaterThan),
|
||||||
|
"<=" => Ok(Operator::LessThanOrEqual),
|
||||||
|
">=" => Ok(Operator::GreaterThanOrEqual),
|
||||||
|
_ => Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Item {
|
impl Item {
|
||||||
@ -23,6 +62,7 @@ impl Item {
|
|||||||
Item::Bare(s) => Value::Primitive(Primitive::String(s.clone())),
|
Item::Bare(s) => Value::Primitive(Primitive::String(s.clone())),
|
||||||
Item::Int(i) => Value::Primitive(Primitive::Int(*i)),
|
Item::Int(i) => Value::Primitive(Primitive::Int(*i)),
|
||||||
Item::Boolean(b) => Value::Primitive(Primitive::Boolean(*b)),
|
Item::Boolean(b) => Value::Primitive(Primitive::Boolean(*b)),
|
||||||
|
Item::Operator(o) => Value::Primitive(Primitive::Operator(o.clone())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -33,6 +73,7 @@ crate fn print_items(items: &[Item]) -> String {
|
|||||||
Item::Quoted(s) => format!("{:?}", s),
|
Item::Quoted(s) => format!("{:?}", s),
|
||||||
Item::Int(i) => format!("{:?}", i),
|
Item::Int(i) => format!("{:?}", i),
|
||||||
Item::Boolean(b) => format!("{:?}", b),
|
Item::Boolean(b) => format!("{:?}", b),
|
||||||
|
Item::Operator(o) => o.print(),
|
||||||
});
|
});
|
||||||
|
|
||||||
itertools::join(formatted, " ")
|
itertools::join(formatted, " ")
|
||||||
@ -45,6 +86,10 @@ impl Item {
|
|||||||
Item::Bare(s) => Ok(s),
|
Item::Bare(s) => Ok(s),
|
||||||
Item::Boolean(i) => Err(ShellError::string(format!("{} is not a valid command", i))),
|
Item::Boolean(i) => Err(ShellError::string(format!("{} is not a valid command", i))),
|
||||||
Item::Int(i) => Err(ShellError::string(format!("{} is not a valid command", i))),
|
Item::Int(i) => Err(ShellError::string(format!("{} is not a valid command", i))),
|
||||||
|
Item::Operator(x) => Err(ShellError::string(format!(
|
||||||
|
"{:?} is not a valid command",
|
||||||
|
x
|
||||||
|
))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -62,6 +107,18 @@ fn unquoted(s: &str) -> IResult<&str, Item> {
|
|||||||
is_not(" |")(s).map(|(a, b)| (a, Item::Bare(b.to_string())))
|
is_not(" |")(s).map(|(a, b)| (a, Item::Bare(b.to_string())))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn operator(s: &str) -> IResult<&str, Item> {
|
||||||
|
alt((
|
||||||
|
tag("=="),
|
||||||
|
tag("!="),
|
||||||
|
tag("<"),
|
||||||
|
tag(">"),
|
||||||
|
tag("<="),
|
||||||
|
tag(">="),
|
||||||
|
))(s)
|
||||||
|
.map(|(a, b)| (a, Item::Operator(FromStr::from_str(b).unwrap())))
|
||||||
|
}
|
||||||
|
|
||||||
fn int(s: &str) -> IResult<&str, Item> {
|
fn int(s: &str) -> IResult<&str, Item> {
|
||||||
is_a("1234567890")(s).map(|(a, b)| (a, Item::Int(FromStr::from_str(b).unwrap())))
|
is_a("1234567890")(s).map(|(a, b)| (a, Item::Int(FromStr::from_str(b).unwrap())))
|
||||||
}
|
}
|
||||||
@ -72,7 +129,7 @@ fn boolean(s: &str) -> IResult<&str, Item> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn command_token(s: &str) -> IResult<&str, Item> {
|
fn command_token(s: &str) -> IResult<&str, Item> {
|
||||||
alt((boolean, int, quoted, unquoted))(s)
|
alt((boolean, int, operator, quoted, unquoted))(s)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn command_args(s: &str) -> IResult<&str, Vec<Item>> {
|
fn command_args(s: &str) -> IResult<&str, Vec<Item>> {
|
||||||
|
Loading…
Reference in New Issue
Block a user