diff --git a/crates/nu-command/src/commands/append.rs b/crates/nu-command/src/commands/append.rs index 2ed0c7f33d..d573d557f9 100644 --- a/crates/nu-command/src/commands/append.rs +++ b/crates/nu-command/src/commands/append.rs @@ -1,7 +1,7 @@ use crate::prelude::*; use nu_engine::WholeStreamCommand; use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, Signature, SyntaxShape, UntaggedValue, Value}; +use nu_protocol::{Signature, SyntaxShape, UntaggedValue, Value}; #[derive(Deserialize)] struct Arguments { @@ -27,13 +27,14 @@ impl WholeStreamCommand for Command { "Append a row to the table." } - fn run_with_actions(&self, args: CommandArgs) -> Result { - let (Arguments { mut value }, input) = args.process()?; + fn run(&self, args: CommandArgs) -> Result { + let (Arguments { mut value }, mut input) = args.process()?; - let input: Vec = input.collect(); + let mut prepend = vec![]; - if let Some(first) = input.get(0) { + if let Some(first) = input.next() { value.tag = first.tag(); + prepend.push(first); } // Checks if we are trying to append a row literal @@ -47,11 +48,10 @@ impl WholeStreamCommand for Command { } } - Ok(input + Ok(prepend .into_iter() - .chain(vec![value]) - .map(ReturnSuccess::value) - .to_action_stream()) + .chain(input.into_iter().chain(vec![value])) + .to_output_stream()) } fn examples(&self) -> Vec { diff --git a/crates/nu-command/src/commands/length.rs b/crates/nu-command/src/commands/length.rs index ffb0786896..4dffcd8acb 100644 --- a/crates/nu-command/src/commands/length.rs +++ b/crates/nu-command/src/commands/length.rs @@ -2,7 +2,7 @@ use crate::prelude::*; use nu_engine::WholeStreamCommand; use nu_errors::ShellError; -use nu_protocol::{ReturnSuccess, ReturnValue, Signature, UntaggedValue}; +use nu_protocol::{Signature, UntaggedValue, Value}; pub struct Length; @@ -28,7 +28,7 @@ impl WholeStreamCommand for Length { "Show the total number of rows or items." } - fn run_with_actions(&self, args: CommandArgs) -> Result { + fn run(&self, args: CommandArgs) -> Result { let tag = args.call_info.name_tag.clone(); let (LengthArgs { column }, input) = args.process()?; @@ -38,7 +38,7 @@ impl WholeStreamCommand for Length { done: false, tag, } - .to_action_stream()) + .to_output_stream()) } fn examples(&self) -> Vec { @@ -65,7 +65,7 @@ struct CountIterator { } impl Iterator for CountIterator { - type Item = ReturnValue; + type Item = Value; fn next(&mut self) -> Option { if self.done { @@ -79,7 +79,7 @@ impl Iterator for CountIterator { match &first.value { UntaggedValue::Row(dictionary) => dictionary.length(), _ => { - return Some(Err(ShellError::labeled_error( + return Some(Value::error(ShellError::labeled_error( "Cannot obtain column length", "cannot obtain column length", self.tag.clone(), @@ -94,9 +94,7 @@ impl Iterator for CountIterator { input.count() }; - Some(Ok(ReturnSuccess::Value( - UntaggedValue::int(length).into_value(self.tag.clone()), - ))) + Some(UntaggedValue::int(length).into_value(self.tag.clone())) } } diff --git a/crates/nu-command/src/commands/prepend.rs b/crates/nu-command/src/commands/prepend.rs index 9e06b28aeb..d4f8eacb25 100644 --- a/crates/nu-command/src/commands/prepend.rs +++ b/crates/nu-command/src/commands/prepend.rs @@ -27,7 +27,7 @@ impl WholeStreamCommand for Prepend { "Prepend the given row to the front of the table." } - fn run_with_actions(&self, args: CommandArgs) -> Result { + fn run(&self, args: CommandArgs) -> Result { prepend(args) } @@ -45,12 +45,12 @@ impl WholeStreamCommand for Prepend { } } -fn prepend(args: CommandArgs) -> Result { +fn prepend(args: CommandArgs) -> Result { let (PrependArgs { row }, input) = args.process()?; let bos = vec![row].into_iter(); - Ok(bos.chain(input).to_action_stream()) + Ok(bos.chain(input).to_output_stream()) } #[cfg(test)] diff --git a/crates/nu-command/src/commands/where_.rs b/crates/nu-command/src/commands/where_.rs index ac2fbc7097..7c28bc516e 100644 --- a/crates/nu-command/src/commands/where_.rs +++ b/crates/nu-command/src/commands/where_.rs @@ -3,7 +3,9 @@ use nu_engine::evaluate_baseline_expr; use nu_engine::WholeStreamCommand; use nu_errors::ShellError; use nu_protocol::{ - hir::CapturedBlock, hir::ClassifiedCommand, ReturnSuccess, Signature, SyntaxShape, + hir::CapturedBlock, + hir::{ClassifiedCommand, SpannedExpression}, + Signature, SyntaxShape, Value, }; pub struct Command; @@ -30,7 +32,7 @@ impl WholeStreamCommand for Command { "Filter table to match the condition." } - fn run_with_actions(&self, args: CommandArgs) -> Result { + fn run(&self, args: CommandArgs) -> Result { where_command(args) } @@ -59,8 +61,8 @@ impl WholeStreamCommand for Command { ] } } -fn where_command(raw_args: CommandArgs) -> Result { - let ctx = Arc::new(EvaluationContext::from_args(&raw_args)); +fn where_command(raw_args: CommandArgs) -> Result { + let context = Arc::new(EvaluationContext::from_args(&raw_args)); let tag = raw_args.call_info.name_tag.clone(); let (Arguments { block }, input) = raw_args.process()?; let condition = { @@ -92,34 +94,13 @@ fn where_command(raw_args: CommandArgs) -> Result { } }; - Ok(input - .filter_map(move |input| { - let condition = condition.clone(); - let ctx = ctx.clone(); - - ctx.scope.enter_scope(); - ctx.scope.add_vars(&block.captured.entries); - ctx.scope.add_var("$it", input.clone()); - - //FIXME: should we use the scope that's brought in as well? - let condition = evaluate_baseline_expr(&condition, &*ctx); - ctx.scope.exit_scope(); - - match condition { - Ok(condition) => match condition.as_bool() { - Ok(b) => { - if b { - Some(Ok(ReturnSuccess::Value(input))) - } else { - None - } - } - Err(e) => Some(Err(e)), - }, - Err(e) => Some(Err(e)), - } - }) - .to_action_stream()) + Ok(WhereIterator { + block, + condition, + context, + input, + } + .to_output_stream()) } #[cfg(test)] @@ -134,3 +115,40 @@ mod tests { test_examples(Command {}) } } + +struct WhereIterator { + condition: Box, + context: Arc, + input: InputStream, + block: CapturedBlock, +} + +impl Iterator for WhereIterator { + type Item = Value; + + fn next(&mut self) -> Option { + while let Some(x) = self.input.next() { + self.context.scope.enter_scope(); + self.context.scope.add_vars(&self.block.captured.entries); + self.context.scope.add_var("$it", x.clone()); + + //FIXME: should we use the scope that's brought in as well? + let condition = evaluate_baseline_expr(&self.condition, &self.context); + self.context.scope.exit_scope(); + + match condition { + Ok(condition) => match condition.as_bool() { + Ok(b) => { + if b { + return Some(x); + } + } + Err(e) => return Some(Value::error(e)), + }, + Err(e) => return Some(Value::error(e)), + } + } + + None + } +}