From d9ae66791a6d5eca9e76422815a1f5d0075dd0ea Mon Sep 17 00:00:00 2001 From: Jonathan Turner Date: Tue, 8 Sep 2020 05:30:11 +1200 Subject: [PATCH] allow decimals as a range boundary (#2509) --- crates/nu-cli/src/commands/echo.rs | 39 +++++++++++++++++------ crates/nu-data/src/base.rs | 2 +- tests/shell/pipeline/commands/internal.rs | 12 +++++++ 3 files changed, 42 insertions(+), 11 deletions(-) diff --git a/crates/nu-cli/src/commands/echo.rs b/crates/nu-cli/src/commands/echo.rs index afb21acfd5..c5910b64ec 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 7e825c0163..8989ebf491 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 69dad9bf17..065f7d10b3 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!(