Fix for loop ctrlc not terminating (#5003)

This commit is contained in:
JT 2022-03-28 19:13:43 +13:00 committed by GitHub
parent a87f53072a
commit 2e3b74f1b2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 37 additions and 19 deletions

View File

@ -125,7 +125,7 @@ https://www.nushell.sh/book/thinking_in_nushell.html#parsing-and-evaluation-are-
.filter(|x| !x.is_nothing())
.into_pipeline_data(ctrlc)),
Value::Range { val, .. } => Ok(val
.into_range_iter()?
.into_range_iter(ctrlc.clone())?
.enumerate()
.map(move |(idx, x)| {
stack.with_env(&orig_env_vars, &orig_env_hidden);

View File

@ -71,7 +71,7 @@ impl Command for ParEach {
match input {
PipelineData::Value(Value::Range { val, .. }, ..) => Ok(val
.into_range_iter()?
.into_range_iter(ctrlc.clone())?
.enumerate()
.par_bridge()
.map(move |(idx, x)| {

View File

@ -81,7 +81,7 @@ pub fn calculate(
}
PipelineData::Value(Value::Range { val, .. }, ..) => {
let new_vals: Result<Vec<Value>, ShellError> = val
.into_range_iter()?
.into_range_iter(None)?
.map(|val| mf(&[val], &name))
.collect();

View File

@ -283,9 +283,10 @@ impl PipelineData {
}
}
PipelineData::Value(Value::Range { val, .. }, ..) => {
Ok(val.into_range_iter()?.map(f).into_pipeline_data(ctrlc))
}
PipelineData::Value(Value::Range { val, .. }, ..) => Ok(val
.into_range_iter(ctrlc.clone())?
.map(f)
.into_pipeline_data(ctrlc)),
PipelineData::Value(v, ..) => match f(v) {
Value::Error { error } => Err(error),
v => Ok(v.into_pipeline_data()),
@ -337,10 +338,12 @@ impl PipelineData {
.into_pipeline_data(ctrlc))
}
}
PipelineData::Value(Value::Range { val, .. }, ..) => match val.into_range_iter() {
Ok(iter) => Ok(iter.flat_map(f).into_pipeline_data(ctrlc)),
Err(error) => Err(error),
},
PipelineData::Value(Value::Range { val, .. }, ..) => {
match val.into_range_iter(ctrlc.clone()) {
Ok(iter) => Ok(iter.flat_map(f).into_pipeline_data(ctrlc)),
Err(error) => Err(error),
}
}
PipelineData::Value(v, ..) => Ok(f(v).into_iter().into_pipeline_data(ctrlc)),
}
}
@ -392,9 +395,10 @@ impl PipelineData {
}
}
}
PipelineData::Value(Value::Range { val, .. }, ..) => {
Ok(val.into_range_iter()?.filter(f).into_pipeline_data(ctrlc))
}
PipelineData::Value(Value::Range { val, .. }, ..) => Ok(val
.into_range_iter(ctrlc.clone())?
.filter(f)
.into_pipeline_data(ctrlc)),
PipelineData::Value(v, ..) => {
if f(&v) {
Ok(v.into_pipeline_data())
@ -425,7 +429,7 @@ impl IntoIterator for PipelineData {
))
}
PipelineData::Value(Value::Range { val, .. }, metadata) => {
match val.into_range_iter() {
match val.into_range_iter(None) {
Ok(iter) => PipelineIterator(PipelineData::ListStream(
ListStream {
stream: Box::new(iter),

View File

@ -605,7 +605,7 @@ impl Value {
}
}
Value::Range { val, .. } => {
if let Some(item) = val.clone().into_range_iter()?.nth(*count) {
if let Some(item) = val.clone().into_range_iter(None)?.nth(*count) {
current = item.clone();
} else {
return Err(ShellError::AccessBeyondEndOfStream(*origin_span));

View File

@ -1,5 +1,8 @@
use serde::{Deserialize, Serialize};
use std::cmp::Ordering;
use std::{
cmp::Ordering,
sync::{atomic::AtomicBool, Arc},
};
/// A Range is an iterator over integers.
use crate::{
@ -122,10 +125,13 @@ impl Range {
}
}
pub fn into_range_iter(self) -> Result<RangeIterator, ShellError> {
pub fn into_range_iter(
self,
ctrlc: Option<Arc<AtomicBool>>,
) -> Result<RangeIterator, ShellError> {
let span = self.from.span()?;
Ok(RangeIterator::new(self, span))
Ok(RangeIterator::new(self, ctrlc, span))
}
}
@ -155,10 +161,11 @@ pub struct RangeIterator {
moves_up: bool,
incr: Value,
done: bool,
ctrlc: Option<Arc<AtomicBool>>,
}
impl RangeIterator {
pub fn new(range: Range, span: Span) -> RangeIterator {
pub fn new(range: Range, ctrlc: Option<Arc<AtomicBool>>, span: Span) -> RangeIterator {
let moves_up = range.moves_up();
let is_end_inclusive = range.is_end_inclusive();
@ -183,6 +190,7 @@ impl RangeIterator {
is_end_inclusive,
done: false,
incr: range.incr,
ctrlc,
}
}
}
@ -194,6 +202,12 @@ impl Iterator for RangeIterator {
return None;
}
if let Some(ctrlc) = &self.ctrlc {
if ctrlc.load(core::sync::atomic::Ordering::SeqCst) {
return None;
}
}
let ordering = if matches!(self.end, Value::Nothing { .. }) {
Some(Ordering::Less)
} else {