diff --git a/crates/nu-cli/src/commands/do_.rs b/crates/nu-cli/src/commands/do_.rs index 7e148726b1..9fd4264f0d 100644 --- a/crates/nu-cli/src/commands/do_.rs +++ b/crates/nu-cli/src/commands/do_.rs @@ -2,9 +2,7 @@ use crate::commands::classified::block::run_block; use crate::commands::WholeStreamCommand; use crate::prelude::*; use nu_errors::ShellError; -use nu_protocol::{ - hir::CapturedBlock, hir::ExternalRedirection, ReturnSuccess, Signature, SyntaxShape, Value, -}; +use nu_protocol::{hir::CapturedBlock, hir::ExternalRedirection, Signature, SyntaxShape, Value}; pub struct Do; @@ -48,7 +46,7 @@ impl WholeStreamCommand for Do { Example { description: "Run the block and ignore errors", example: r#"do -i { thisisnotarealcommand }"#, - result: Some(vec![Value::nothing()]), + result: Some(vec![]), }, ] } @@ -98,7 +96,7 @@ async fn do_(raw_args: CommandArgs) -> Result { context.clear_errors(); Ok(futures::stream::iter(output).to_output_stream()) } - Err(_) => Ok(OutputStream::one(ReturnSuccess::value(Value::nothing()))), + Err(_) => Ok(OutputStream::empty()), } } else { result.map(|x| x.to_output_stream()) diff --git a/crates/nu-cli/src/commands/math/eval.rs b/crates/nu-cli/src/commands/math/eval.rs index 28383443d0..78ccb5e373 100644 --- a/crates/nu-cli/src/commands/math/eval.rs +++ b/crates/nu-cli/src/commands/math/eval.rs @@ -50,37 +50,48 @@ pub async fn eval(args: CommandArgs) -> Result { let name = args.call_info.name_tag.span; let (SubCommandArgs { expression }, input) = args.process().await?; - Ok(input - .map(move |x| { - if let Some(Tagged { - tag, - item: expression, - }) = &expression - { - UntaggedValue::string(expression).into_value(tag) - } else { - x - } - }) - .map(move |input| { - if let Ok(string) = input.as_string() { - match parse(&string, &input.tag) { - Ok(value) => ReturnSuccess::value(value), - Err(err) => Err(ShellError::labeled_error( - "Math evaluation error", - err, - &input.tag.span, - )), + if let Some(string) = expression { + match parse(&string, &string.tag) { + Ok(value) => Ok(OutputStream::one(ReturnSuccess::value(value))), + Err(err) => Err(ShellError::labeled_error( + "Math evaluation error", + err, + &string.tag.span, + )), + } + } else { + Ok(input + .map(move |x| { + if let Some(Tagged { + tag, + item: expression, + }) = &expression + { + UntaggedValue::string(expression).into_value(tag) + } else { + x } - } else { - Err(ShellError::labeled_error( - "Expected a string from pipeline", - "requires string input", - name, - )) - } - }) - .to_output_stream()) + }) + .map(move |input| { + if let Ok(string) = input.as_string() { + match parse(&string, &input.tag) { + Ok(value) => ReturnSuccess::value(value), + Err(err) => Err(ShellError::labeled_error( + "Math evaluation error", + err, + &input.tag.span, + )), + } + } else { + Err(ShellError::labeled_error( + "Expected a string from pipeline", + "requires string input", + name, + )) + } + }) + .to_output_stream()) + } } pub fn parse>(math_expression: &str, tag: T) -> Result { diff --git a/crates/nu-cli/src/commands/math/sum.rs b/crates/nu-cli/src/commands/math/sum.rs index debb4de7ab..4f44cf5cf0 100644 --- a/crates/nu-cli/src/commands/math/sum.rs +++ b/crates/nu-cli/src/commands/math/sum.rs @@ -73,7 +73,11 @@ pub fn summation(values: &[Value], name: &Tag) -> Result { let sum = reducer_for(Reduce::Summation); let first = values.get(0).ok_or_else(|| { - ShellError::unexpected("Cannot perform aggregate math operation on empty data") + ShellError::labeled_error( + "Cannot perform aggregate math operation on empty data", + "expected input", + name.span, + ) })?; match first { diff --git a/crates/nu-cli/src/commands/reduce.rs b/crates/nu-cli/src/commands/reduce.rs index fa67b1eae6..f92f7a144b 100644 --- a/crates/nu-cli/src/commands/reduce.rs +++ b/crates/nu-cli/src/commands/reduce.rs @@ -6,7 +6,7 @@ use crate::{CommandArgs, Example, OutputStream}; use futures::stream::once; use nu_errors::ShellError; use nu_parser::ParserScope; -use nu_protocol::{hir::CapturedBlock, Primitive, Signature, SyntaxShape, UntaggedValue, Value}; +use nu_protocol::{hir::CapturedBlock, Signature, SyntaxShape, UntaggedValue, Value}; use nu_source::Tagged; pub struct Reduce; @@ -93,22 +93,25 @@ async fn process_row( } async fn reduce(raw_args: CommandArgs) -> Result { + let span = raw_args.call_info.name_tag.span; let context = Arc::new(EvaluationContext::from_raw(&raw_args)); let (reduce_args, mut input): (ReduceArgs, _) = raw_args.process().await?; let block = Arc::new(reduce_args.block); - let (ioffset, start) = match reduce_args.fold { - None => { - let first = input - .next() - .await - .expect("empty stream expected to contain Primitive::Nothing"); - if let UntaggedValue::Primitive(Primitive::Nothing) = first.value { - return Err(ShellError::missing_value(None, "empty input")); - } + let (ioffset, start) = if !input.is_empty() { + match reduce_args.fold { + None => { + let first = input.next().await.expect("non-empty stream"); - (1, first) + (1, first) + } + Some(acc) => (0, acc), } - Some(acc) => (0, acc), + } else { + return Err(ShellError::labeled_error( + "Expected input", + "needs input", + span, + )); }; if reduce_args.numbered.item { diff --git a/crates/nu-cli/src/commands/str_/collect.rs b/crates/nu-cli/src/commands/str_/collect.rs index 07e958ff42..a858ba54f3 100644 --- a/crates/nu-cli/src/commands/str_/collect.rs +++ b/crates/nu-cli/src/commands/str_/collect.rs @@ -49,12 +49,39 @@ pub async fn collect(args: CommandArgs) -> Result { let strings: Vec> = input.map(|value| value.as_string()).collect().await; - let strings: Vec = strings.into_iter().collect::>()?; - let output = strings.join(&separator); + let strings: Result, _> = strings.into_iter().collect::>(); - Ok(OutputStream::one(ReturnSuccess::value( - UntaggedValue::string(output).into_value(tag), - ))) + match strings { + Ok(strings) => { + let output = strings.join(&separator); + + Ok(OutputStream::one(ReturnSuccess::value( + UntaggedValue::string(output).into_value(tag), + ))) + } + Err(err) => match err.error { + nu_errors::ProximateShellError::TypeError { actual, .. } => { + if let Some(item) = actual.item { + Err(ShellError::labeled_error_with_secondary( + "could not convert to string", + format!("tried to convert '{}' in input to a string", item), + tag.span, + format!("'{}' value originated here", item), + actual.span, + )) + } else { + Err(ShellError::labeled_error_with_secondary( + "could not convert to string", + "failed to convert input to strings", + tag.span, + "non-string found here", + actual.span, + )) + } + } + _ => Err(err), + }, + } } #[cfg(test)] diff --git a/crates/nu-cli/tests/commands/math/sum.rs b/crates/nu-cli/tests/commands/math/sum.rs index dfc08973f1..6ce01ea72d 100644 --- a/crates/nu-cli/tests/commands/math/sum.rs +++ b/crates/nu-cli/tests/commands/math/sum.rs @@ -33,13 +33,6 @@ fn all() { }) } -#[test] -fn outputs_zero_with_no_input() { - let actual = nu!(cwd: ".", "math sum"); - - assert_eq!(actual.out, "0"); -} - #[test] #[allow(clippy::unreadable_literal)] #[allow(clippy::float_cmp)] diff --git a/crates/nu-cli/tests/commands/reduce.rs b/crates/nu-cli/tests/commands/reduce.rs index 59ef2d7ae6..108118767d 100644 --- a/crates/nu-cli/tests/commands/reduce.rs +++ b/crates/nu-cli/tests/commands/reduce.rs @@ -103,5 +103,5 @@ fn error_reduce_empty() { ) ); - assert!(actual.err.contains("empty input")); + assert!(actual.err.contains("needs input")); } diff --git a/crates/nu-stream/src/input.rs b/crates/nu-stream/src/input.rs index ce40e63d22..6a4ad21e69 100644 --- a/crates/nu-stream/src/input.rs +++ b/crates/nu-stream/src/input.rs @@ -1,5 +1,5 @@ use crate::prelude::*; -use futures::stream::{iter, once}; +use futures::stream::iter; use nu_errors::ShellError; use nu_protocol::{Primitive, Type, UntaggedValue, Value}; use nu_source::{PrettyDebug, Tag, Tagged, TaggedItem}; @@ -14,7 +14,7 @@ pub struct InputStream { impl InputStream { pub fn empty() -> InputStream { InputStream { - values: once(async { UntaggedValue::nothing().into_untagged_value() }).boxed(), + values: futures::stream::empty().boxed(), empty: true, } }