diff --git a/crates/nu-cli/src/commands/echo.rs b/crates/nu-cli/src/commands/echo.rs index afb21acfd..c5910b64e 100644 --- a/crates/nu-cli/src/commands/echo.rs +++ b/crates/nu-cli/src/commands/echo.rs @@ -81,7 +81,6 @@ struct RangeIterator { end: Primitive, tag: Tag, is_end_inclusive: bool, - is_done: bool, } impl RangeIterator { @@ -96,7 +95,6 @@ impl RangeIterator { end: range.to.0.item, tag, is_end_inclusive: matches!(range.to.1, RangeInclusion::Inclusive), - is_done: false, } } } @@ -104,14 +102,40 @@ impl RangeIterator { impl Iterator for RangeIterator { type Item = Result; fn next(&mut self) -> Option { - if self.curr != self.end { + let ordering = if self.end == Primitive::Nothing { + Ordering::Less + } else { + let result = + nu_data::base::coerce_compare_primitive(&self.curr, &self.end).map_err(|_| { + ShellError::labeled_error( + "Cannot create range", + "unsupported range", + self.tag.span, + ) + }); + + if let Err(result) = result { + return Some(Err(result)); + } + + let result = result + .expect("Internal error: the error case was already protected, but that failed"); + + result.compare() + }; + + use std::cmp::Ordering; + + if (ordering == Ordering::Less) || (self.is_end_inclusive && ordering == Ordering::Equal) { let output = UntaggedValue::Primitive(self.curr.clone()).into_value(self.tag.clone()); - self.curr = match nu_data::value::compute_values( + let next_value = nu_data::value::compute_values( Operator::Plus, &UntaggedValue::Primitive(self.curr.clone()), &UntaggedValue::int(1), - ) { + ); + + self.curr = match next_value { Ok(result) => match result { UntaggedValue::Primitive(p) => p, _ => { @@ -128,11 +152,6 @@ impl Iterator for RangeIterator { } }; Some(ReturnSuccess::value(output)) - } else if self.is_end_inclusive && !self.is_done { - self.is_done = true; - Some(ReturnSuccess::value( - UntaggedValue::Primitive(self.curr.clone()).into_value(self.tag.clone()), - )) } else { // TODO: add inclusive/exclusive ranges None diff --git a/crates/nu-data/src/base.rs b/crates/nu-data/src/base.rs index 7e825c016..8989ebf49 100644 --- a/crates/nu-data/src/base.rs +++ b/crates/nu-data/src/base.rs @@ -126,7 +126,7 @@ pub fn coerce_compare( } } -fn coerce_compare_primitive( +pub fn coerce_compare_primitive( left: &Primitive, right: &Primitive, ) -> Result { diff --git a/tests/shell/pipeline/commands/internal.rs b/tests/shell/pipeline/commands/internal.rs index 69dad9bf1..065f7d10b 100644 --- a/tests/shell/pipeline/commands/internal.rs +++ b/tests/shell/pipeline/commands/internal.rs @@ -502,6 +502,18 @@ fn range_with_open_right() { assert_eq!(actual.out, "95"); } +#[test] +fn range_with_mixed_types() { + let actual = nu!( + cwd: ".", + r#" + echo 1..10.5 | math sum + "# + ); + + assert_eq!(actual.out, "55"); +} + #[test] fn it_expansion_of_tables() { let actual = nu!(