diff --git a/crates/nu-command/src/strings/parse.rs b/crates/nu-command/src/strings/parse.rs index f74fd42371..4a80119e03 100644 --- a/crates/nu-command/src/strings/parse.rs +++ b/crates/nu-command/src/strings/parse.rs @@ -1,3 +1,6 @@ +use std::sync::atomic::{AtomicBool, Ordering}; +use std::sync::Arc; + use fancy_regex::Regex; use nu_engine::CallExt; use nu_protocol::ast::Call; @@ -230,6 +233,7 @@ fn operate( regex: regex_pattern, columns, stream: stream.stream, + ctrlc: ctrlc.clone(), }, ctrlc, ), @@ -329,6 +333,7 @@ pub struct ParseStreamer { regex: Regex, columns: Vec, stream: Box + Send + 'static>, + ctrlc: Option>, } impl Iterator for ParseStreamer { @@ -338,27 +343,38 @@ impl Iterator for ParseStreamer { return Some(self.excess.remove(0)); } - let v = self.stream.next(); + loop { + if let Some(ctrlc) = &self.ctrlc { + if ctrlc.load(Ordering::SeqCst) { + break None; + } + } - if let Some(v) = v { - match v.as_string() { - Ok(s) => stream_helper( - self.regex.clone(), - v.span().unwrap_or(self.span), - s, - self.columns.clone(), - &mut self.excess, - ), - Err(_) => Some(Value::Error { + let Some(v) = self.stream.next() else { return None }; + + let Ok(s) = v.as_string() else { + return Some(Value::Error { error: Box::new(ShellError::PipelineMismatch { exp_input_type: "string".into(), dst_span: self.span, src_span: v.span().unwrap_or(self.span), }), - }), - } - } else { - None + }) + }; + + let parsed = stream_helper( + self.regex.clone(), + v.span().unwrap_or(self.span), + s, + self.columns.clone(), + &mut self.excess, + ); + + if parsed.is_none() { + continue; + }; + + return parsed; } } } diff --git a/crates/nu-command/tests/commands/parse.rs b/crates/nu-command/tests/commands/parse.rs index b00641d2d8..ec81b3fe36 100644 --- a/crates/nu-command/tests/commands/parse.rs +++ b/crates/nu-command/tests/commands/parse.rs @@ -197,4 +197,18 @@ mod regex { assert_eq!(actual.out, "table (stream)") } + + #[test] + fn parse_does_not_truncate_list_streams() { + let actual = nu!(pipeline( + r#" + [a b c] + | each {|x| $x} + | parse --regex "[ac]" + | length + "# + )); + + assert_eq!(actual.out, "2"); + } }