Move where to helper (#302)

This commit is contained in:
JT 2021-11-07 15:40:44 +13:00 committed by GitHub
parent 7e070e2e5b
commit 00a8752c76
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 56 additions and 41 deletions

11
Cargo.lock generated
View file

@ -2,6 +2,16 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 3 version = 3
[[package]]
name = "Inflector"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
dependencies = [
"lazy_static",
"regex",
]
[[package]] [[package]]
name = "addr2line" name = "addr2line"
version = "0.17.0" version = "0.17.0"
@ -680,6 +690,7 @@ dependencies = [
name = "nu-command" name = "nu-command"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"Inflector",
"bytesize", "bytesize",
"chrono", "chrono",
"chrono-humanize", "chrono-humanize",

View file

@ -1,10 +1,7 @@
use nu_engine::eval_expression; use nu_engine::eval_expression;
use nu_protocol::ast::{Call, Expr, Expression}; use nu_protocol::ast::{Call, Expr, Expression};
use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::engine::{Command, EngineState, Stack};
use nu_protocol::{ use nu_protocol::{PipelineData, ShellError, Signature, SyntaxShape};
IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, ShellError, Signature,
SyntaxShape, Value,
};
#[derive(Clone)] #[derive(Clone)]
pub struct Where; pub struct Where;
@ -29,13 +26,12 @@ impl Command for Where {
call: &Call, call: &Call,
input: PipelineData, input: PipelineData,
) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> { ) -> Result<nu_protocol::PipelineData, nu_protocol::ShellError> {
let head = call.head;
let cond = call.positional[0].clone(); let cond = call.positional[0].clone();
let ctrlc = engine_state.ctrlc.clone(); let ctrlc = engine_state.ctrlc.clone();
let engine_state = engine_state.clone(); let engine_state = engine_state.clone();
// FIXME: very expensive // FIXME: expensive
let mut stack = stack.clone(); let mut stack = stack.clone();
let (var_id, cond) = match cond { let (var_id, cond) = match cond {
@ -46,43 +42,18 @@ impl Command for Where {
_ => return Err(ShellError::InternalError("Expected row condition".into())), _ => return Err(ShellError::InternalError("Expected row condition".into())),
}; };
match input { input.filter(
PipelineData::Stream(stream) => Ok(stream move |value| {
.filter(move |value| { stack.add_var(var_id, value.clone());
stack.add_var(var_id, value.clone());
let result = eval_expression(&engine_state, &mut stack, &cond); let result = eval_expression(&engine_state, &mut stack, &cond);
match result { match result {
Ok(result) => result.is_true(), Ok(result) => result.is_true(),
_ => false, _ => false,
}
})
.into_pipeline_data(ctrlc)),
PipelineData::Value(Value::List { vals, .. }) => Ok(vals
.into_iter()
.filter(move |value| {
stack.add_var(var_id, value.clone());
let result = eval_expression(&engine_state, &mut stack, &cond);
match result {
Ok(result) => result.is_true(),
_ => false,
}
})
.into_pipeline_data(ctrlc)),
PipelineData::Value(x) => {
stack.add_var(var_id, x.clone());
let result = eval_expression(&engine_state, &mut stack, &cond)?;
if result.is_true() {
Ok(x.into_pipeline_data())
} else {
Ok(PipelineData::new(head))
} }
} },
} ctrlc,
)
} }
} }

View file

@ -138,6 +138,34 @@ impl PipelineData {
PipelineData::Value(v) => Ok(f(v).into_iter().into_pipeline_data(ctrlc)), PipelineData::Value(v) => Ok(f(v).into_iter().into_pipeline_data(ctrlc)),
} }
} }
pub fn filter<F>(
self,
mut f: F,
ctrlc: Option<Arc<AtomicBool>>,
) -> Result<PipelineData, ShellError>
where
Self: Sized,
F: FnMut(&Value) -> bool + 'static + Send,
{
match self {
PipelineData::Value(Value::List { vals, .. }) => {
Ok(vals.into_iter().filter(f).into_pipeline_data(ctrlc))
}
PipelineData::Stream(stream) => Ok(stream.filter(f).into_pipeline_data(ctrlc)),
PipelineData::Value(Value::Range { val, .. }) => match val.into_range_iter() {
Ok(iter) => Ok(iter.filter(f).into_pipeline_data(ctrlc)),
Err(error) => Err(error),
},
PipelineData::Value(v) => {
if f(&v) {
Ok(v.into_pipeline_data())
} else {
Ok(Value::Nothing { span: v.span()? }.into_pipeline_data())
}
}
}
}
} }
// impl Default for PipelineData { // impl Default for PipelineData {

View file

@ -849,3 +849,8 @@ fn range_and_reduction() -> TestResult {
fn precedence_of_or_groups() -> TestResult { fn precedence_of_or_groups() -> TestResult {
run_test(r#"4 mod 3 == 0 || 5 mod 5 == 0"#, "true") run_test(r#"4 mod 3 == 0 || 5 mod 5 == 0"#, "true")
} }
#[test]
fn where_on_ranges() -> TestResult {
run_test(r#"1..10 | where $it > 8 | math sum"#, "19")
}