diff --git a/crates/nu-command/src/commands/echo.rs b/crates/nu-command/src/commands/echo.rs index f8b2c26b46..3db5c7a79a 100644 --- a/crates/nu-command/src/commands/echo.rs +++ b/crates/nu-command/src/commands/echo.rs @@ -76,6 +76,7 @@ struct RangeIterator { end: Primitive, tag: Tag, is_end_inclusive: bool, + moves_up: bool, } impl RangeIterator { @@ -85,9 +86,15 @@ impl RangeIterator { x => x, }; + let end = match range.to.0.item { + Primitive::Nothing => Primitive::Int(u64::MAX.into()), + x => x, + }; + RangeIterator { + moves_up: start <= end, curr: start, - end: range.to.0.item, + end, tag, is_end_inclusive: matches!(range.to.1, RangeInclusion::Inclusive), } @@ -121,7 +128,9 @@ impl Iterator for RangeIterator { use std::cmp::Ordering; - if (ordering == Ordering::Less) || (self.is_end_inclusive && ordering == Ordering::Equal) { + if self.moves_up + && (ordering == Ordering::Less || self.is_end_inclusive && ordering == Ordering::Equal) + { let output = UntaggedValue::Primitive(self.curr.clone()).into_value(self.tag.clone()); let next_value = nu_data::value::compute_values( @@ -130,6 +139,35 @@ impl Iterator for RangeIterator { &UntaggedValue::int(1), ); + self.curr = match next_value { + Ok(result) => match result { + UntaggedValue::Primitive(p) => p, + _ => { + return Some(Err(ShellError::unimplemented( + "Internal error: expected a primitive result from increment", + ))); + } + }, + Err((left_type, right_type)) => { + return Some(Err(ShellError::coerce_error( + left_type.spanned(self.tag.span), + right_type.spanned(self.tag.span), + ))); + } + }; + Some(ReturnSuccess::value(output)) + } else if !self.moves_up + && (ordering == Ordering::Greater + || self.is_end_inclusive && ordering == Ordering::Equal) + { + let output = UntaggedValue::Primitive(self.curr.clone()).into_value(self.tag.clone()); + + 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, @@ -148,7 +186,6 @@ impl Iterator for RangeIterator { }; Some(ReturnSuccess::value(output)) } else { - // TODO: add inclusive/exclusive ranges None } } diff --git a/crates/nu-command/tests/commands/echo.rs b/crates/nu-command/tests/commands/echo.rs index e6f740e465..e23609f9a6 100644 --- a/crates/nu-command/tests/commands/echo.rs +++ b/crates/nu-command/tests/commands/echo.rs @@ -11,3 +11,51 @@ fn echo_range_is_lazy() { assert_eq!(actual.out, "[1,2,3]"); } + +#[test] +fn echo_range_handles_inclusive() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + echo 1..3 | to json + "# + )); + + assert_eq!(actual.out, "[1,2,3]"); +} + +#[test] +fn echo_range_handles_exclusive() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + echo 1..<3 | to json + "# + )); + + assert_eq!(actual.out, "[1,2]"); +} + +#[test] +fn echo_range_handles_inclusive_down() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + echo 3..1 | to json + "# + )); + + assert_eq!(actual.out, "[3,2,1]"); +} + +#[test] +fn echo_range_handles_exclusive_down() { + let actual = nu!( + cwd: "tests/fixtures/formats", pipeline( + r#" + echo 3..<1 | to json + "# + )); + + assert_eq!(actual.out, "[3,2]"); +}