forked from extern/nushell
Add support for skip and where
This commit is contained in:
parent
638093aad6
commit
cbb86b0cab
@ -5,7 +5,9 @@ crate mod ls;
|
||||
crate mod ps;
|
||||
crate mod reject;
|
||||
crate mod select;
|
||||
crate mod skip;
|
||||
crate mod take;
|
||||
crate mod to_array;
|
||||
crate mod where_;
|
||||
|
||||
crate use to_array::to_array;
|
||||
|
29
src/commands/skip.rs
Normal file
29
src/commands/skip.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use crate::errors::ShellError;
|
||||
use crate::prelude::*;
|
||||
use derive_new::new;
|
||||
|
||||
#[derive(new)]
|
||||
pub struct Skip;
|
||||
|
||||
// TODO: "Amount remaining" wrapper
|
||||
|
||||
impl crate::Command for Skip {
|
||||
fn run(&self, args: CommandArgs<'caller>) -> Result<VecDeque<ReturnValue>, ShellError> {
|
||||
let amount = args.args[0].as_int()?;
|
||||
|
||||
let amount = if args.input.len() > amount as usize {
|
||||
amount as usize
|
||||
} else {
|
||||
args.input.len()
|
||||
};
|
||||
|
||||
let out: VecDeque<ReturnValue> = args
|
||||
.input
|
||||
.into_iter()
|
||||
.skip(amount)
|
||||
.map(|v| ReturnValue::Value(v))
|
||||
.collect();
|
||||
|
||||
Ok(out)
|
||||
}
|
||||
}
|
30
src/commands/where_.rs
Normal file
30
src/commands/where_.rs
Normal file
@ -0,0 +1,30 @@
|
||||
use crate::errors::ShellError;
|
||||
use crate::object::base::find;
|
||||
use crate::prelude::*;
|
||||
use derive_new::new;
|
||||
|
||||
#[derive(new)]
|
||||
pub struct Where;
|
||||
|
||||
impl crate::Command for Where {
|
||||
fn run(&self, args: CommandArgs<'caller>) -> Result<VecDeque<ReturnValue>, ShellError> {
|
||||
if args.args.is_empty() {
|
||||
return Err(ShellError::string("select requires a field"));
|
||||
}
|
||||
|
||||
let field: Result<String, _> = args.args[0].as_string();
|
||||
let field = field?;
|
||||
|
||||
let op: Result<String, _> = args.args[1].as_string();
|
||||
let op = op?;
|
||||
|
||||
let objects = args
|
||||
.input
|
||||
.iter()
|
||||
.filter(|item| find(&item, &field, &op, &args.args[2]))
|
||||
.map(|item| ReturnValue::Value(item.copy()))
|
||||
.collect();
|
||||
|
||||
Ok(objects)
|
||||
}
|
||||
}
|
@ -59,10 +59,12 @@ fn main() -> Result<(), Box<Error>> {
|
||||
("ps", Box::new(ps::Ps)),
|
||||
("ls", Box::new(ls::Ls)),
|
||||
("cd", Box::new(cd::Cd)),
|
||||
("skip", Box::new(skip::Skip)),
|
||||
("take", Box::new(take::Take)),
|
||||
("select", Box::new(select::Select)),
|
||||
("reject", Box::new(reject::Reject)),
|
||||
("to-array", Box::new(to_array::ToArray)),
|
||||
("where", Box::new(where_::Where))
|
||||
]);
|
||||
}
|
||||
|
||||
@ -73,6 +75,9 @@ fn main() -> Result<(), Box<Error>> {
|
||||
));
|
||||
|
||||
match readline {
|
||||
Ok(ref line) if line.trim() == "exit" => {
|
||||
break;
|
||||
}
|
||||
Ok(line) => {
|
||||
let result = crate::parser::shell_parser(&line)
|
||||
.map_err(|e| ShellError::string(format!("{:?}", e)))?;
|
||||
|
@ -120,6 +120,17 @@ impl Value {
|
||||
}
|
||||
}
|
||||
|
||||
crate fn as_bool(&self) -> Result<bool, ShellError> {
|
||||
match self {
|
||||
Value::Primitive(Primitive::Boolean(b)) => Ok(*b),
|
||||
// TODO: this should definitely be more general with better errors
|
||||
other => Err(ShellError::string(format!(
|
||||
"Expected integer, got {:?}",
|
||||
other
|
||||
))),
|
||||
}
|
||||
}
|
||||
|
||||
crate fn string(s: impl Into<String>) -> Value {
|
||||
Value::Primitive(Primitive::String(s.into()))
|
||||
}
|
||||
@ -132,6 +143,10 @@ impl Value {
|
||||
Value::Primitive(Primitive::Int(s.into()))
|
||||
}
|
||||
|
||||
crate fn bool(s: impl Into<bool>) -> Value {
|
||||
Value::Primitive(Primitive::Boolean(s.into()))
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
crate fn system_date(s: SystemTime) -> Value {
|
||||
Value::Primitive(Primitive::Date(s.into()))
|
||||
@ -188,3 +203,86 @@ crate fn reject(obj: &Value, fields: &[String]) -> crate::object::Dictionary {
|
||||
|
||||
out
|
||||
}
|
||||
|
||||
crate fn find(obj: &Value, field: &str, op: &str, rhs: &Value) -> bool {
|
||||
let descs = obj.data_descriptors();
|
||||
match descs.iter().find(|d| d.name == *field) {
|
||||
None => false,
|
||||
Some(desc) => {
|
||||
let v = obj.get_data(desc).borrow().copy();
|
||||
//println!("'{:?}' '{}' '{:?}'", v, op, rhs);
|
||||
|
||||
match v {
|
||||
Value::Primitive(Primitive::Boolean(b)) => {
|
||||
match (op, rhs) {
|
||||
("-eq", Value::Primitive(Primitive::Boolean(b2))) => {
|
||||
b == *b2
|
||||
}
|
||||
("-ne", Value::Primitive(Primitive::Boolean(b2))) => {
|
||||
b != *b2
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
Value::Primitive(Primitive::Bytes(i)) => {
|
||||
match (op, rhs) {
|
||||
("-lt", Value::Primitive(Primitive::Int(i2))) => {
|
||||
i < (*i2 as u128)
|
||||
}
|
||||
("-gt", Value::Primitive(Primitive::Int(i2))) => {
|
||||
i > (*i2 as u128)
|
||||
}
|
||||
("-le", Value::Primitive(Primitive::Int(i2))) => {
|
||||
i <= (*i2 as u128)
|
||||
}
|
||||
("-ge", Value::Primitive(Primitive::Int(i2))) => {
|
||||
i >= (*i2 as u128)
|
||||
}
|
||||
("-eq", Value::Primitive(Primitive::Int(i2))) => {
|
||||
i == (*i2 as u128)
|
||||
}
|
||||
("-ne", Value::Primitive(Primitive::Int(i2))) => {
|
||||
i != (*i2 as u128)
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
Value::Primitive(Primitive::Int(i)) => {
|
||||
match (op, rhs) {
|
||||
("-lt", Value::Primitive(Primitive::Int(i2))) => {
|
||||
i < *i2
|
||||
}
|
||||
("-gt", Value::Primitive(Primitive::Int(i2))) => {
|
||||
i > *i2
|
||||
}
|
||||
("-le", Value::Primitive(Primitive::Int(i2))) => {
|
||||
i <= *i2
|
||||
}
|
||||
("-ge", Value::Primitive(Primitive::Int(i2))) => {
|
||||
i >= *i2
|
||||
}
|
||||
("-eq", Value::Primitive(Primitive::Int(i2))) => {
|
||||
i == *i2
|
||||
}
|
||||
("-ne", Value::Primitive(Primitive::Int(i2))) => {
|
||||
i != *i2
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
Value::Primitive(Primitive::String(s)) => {
|
||||
match (op, rhs) {
|
||||
("-eq", Value::Primitive(Primitive::String(s2))) => {
|
||||
s == *s2
|
||||
}
|
||||
("-ne", Value::Primitive(Primitive::String(s2))) => {
|
||||
s != *s2
|
||||
}
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ pub enum Item {
|
||||
Quoted(String),
|
||||
Bare(String),
|
||||
Int(i64),
|
||||
Boolean(bool),
|
||||
}
|
||||
|
||||
impl Item {
|
||||
@ -21,6 +22,7 @@ impl Item {
|
||||
Item::Quoted(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::Boolean(b) => Value::Primitive(Primitive::Boolean(*b)),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -30,6 +32,7 @@ crate fn print_items(items: &[Item]) -> String {
|
||||
Item::Bare(s) => format!("{}", s),
|
||||
Item::Quoted(s) => format!("{:?}", s),
|
||||
Item::Int(i) => format!("{:?}", i),
|
||||
Item::Boolean(b) => format!("{:?}", b),
|
||||
});
|
||||
|
||||
itertools::join(formatted, " ")
|
||||
@ -40,7 +43,7 @@ impl Item {
|
||||
match self {
|
||||
Item::Quoted(s) => s,
|
||||
Item::Bare(s) => s,
|
||||
Item::Int(_) => unimplemented!(),
|
||||
Item::Boolean(_) | Item::Int(_) => unimplemented!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -62,8 +65,13 @@ fn int(s: &str) -> IResult<&str, Item> {
|
||||
is_a("1234567890")(s).map(|(a, b)| (a, Item::Int(FromStr::from_str(b).unwrap())))
|
||||
}
|
||||
|
||||
fn boolean(s: &str) -> IResult<&str, Item> {
|
||||
alt((tag("true"), tag("false")))(s)
|
||||
.map(|(a, b)| (a, Item::Boolean(FromStr::from_str(b).unwrap())))
|
||||
}
|
||||
|
||||
fn command_token(s: &str) -> IResult<&str, Item> {
|
||||
alt((int, quoted, unquoted))(s)
|
||||
alt((boolean, int, quoted, unquoted))(s)
|
||||
}
|
||||
|
||||
fn command_args(s: &str) -> IResult<&str, Vec<Item>> {
|
||||
|
Loading…
Reference in New Issue
Block a user