From 2e3b74f1b22c6ae57afaa734666029ca8377b807 Mon Sep 17 00:00:00 2001 From: JT <547158+jntrnr@users.noreply.github.com> Date: Mon, 28 Mar 2022 19:13:43 +1300 Subject: [PATCH] Fix for loop ctrlc not terminating (#5003) --- crates/nu-command/src/core_commands/for_.rs | 2 +- crates/nu-command/src/filters/par_each.rs | 2 +- crates/nu-command/src/math/utils.rs | 2 +- crates/nu-protocol/src/pipeline_data.rs | 26 ++++++++++++--------- crates/nu-protocol/src/value/mod.rs | 2 +- crates/nu-protocol/src/value/range.rs | 22 +++++++++++++---- 6 files changed, 37 insertions(+), 19 deletions(-) diff --git a/crates/nu-command/src/core_commands/for_.rs b/crates/nu-command/src/core_commands/for_.rs index 52d1d434b..c92ecfb5e 100644 --- a/crates/nu-command/src/core_commands/for_.rs +++ b/crates/nu-command/src/core_commands/for_.rs @@ -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); diff --git a/crates/nu-command/src/filters/par_each.rs b/crates/nu-command/src/filters/par_each.rs index b23abf131..60bb5f099 100644 --- a/crates/nu-command/src/filters/par_each.rs +++ b/crates/nu-command/src/filters/par_each.rs @@ -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)| { diff --git a/crates/nu-command/src/math/utils.rs b/crates/nu-command/src/math/utils.rs index 27dcbcf82..04f73cb74 100644 --- a/crates/nu-command/src/math/utils.rs +++ b/crates/nu-command/src/math/utils.rs @@ -81,7 +81,7 @@ pub fn calculate( } PipelineData::Value(Value::Range { val, .. }, ..) => { let new_vals: Result, ShellError> = val - .into_range_iter()? + .into_range_iter(None)? .map(|val| mf(&[val], &name)) .collect(); diff --git a/crates/nu-protocol/src/pipeline_data.rs b/crates/nu-protocol/src/pipeline_data.rs index a2ee75967..ba694e154 100644 --- a/crates/nu-protocol/src/pipeline_data.rs +++ b/crates/nu-protocol/src/pipeline_data.rs @@ -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), diff --git a/crates/nu-protocol/src/value/mod.rs b/crates/nu-protocol/src/value/mod.rs index 973bb91e0..1f8193729 100644 --- a/crates/nu-protocol/src/value/mod.rs +++ b/crates/nu-protocol/src/value/mod.rs @@ -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)); diff --git a/crates/nu-protocol/src/value/range.rs b/crates/nu-protocol/src/value/range.rs index 91afd33a1..5e90303be 100644 --- a/crates/nu-protocol/src/value/range.rs +++ b/crates/nu-protocol/src/value/range.rs @@ -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 { + pub fn into_range_iter( + self, + ctrlc: Option>, + ) -> Result { 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>, } impl RangeIterator { - pub fn new(range: Range, span: Span) -> RangeIterator { + pub fn new(range: Range, ctrlc: Option>, 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 {