forked from extern/nushell
RangeIterator can also go down (#2913)
This commit is contained in:
parent
3be198d2f5
commit
dff85a7f70
@ -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
|
||||
}
|
||||
}
|
||||
|
@ -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]");
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user