diff --git a/crates/nu-command/src/filters/uniq.rs b/crates/nu-command/src/filters/uniq.rs index 1cdabf6a4b..aed95f24dd 100644 --- a/crates/nu-command/src/filters/uniq.rs +++ b/crates/nu-command/src/filters/uniq.rs @@ -1,3 +1,4 @@ +use crate::input_handler::ctrl_c_was_pressed; use nu_protocol::ast::Call; use nu_protocol::engine::{Command, EngineState, Stack}; use nu_protocol::{ @@ -213,27 +214,30 @@ fn generate_results_with_count(head: Span, uniq_values: Vec) -> Ve } pub fn uniq( - _engine_state: &EngineState, + engine_state: &EngineState, _stack: &mut Stack, call: &Call, input: Vec, item_mapper: Box ValueCounter>, metadata: Option, ) -> Result { + let ctrlc = engine_state.ctrlc.clone(); let head = call.head; let flag_show_count = call.has_flag("count"); let flag_show_repeated = call.has_flag("repeated"); let flag_ignore_case = call.has_flag("ignore-case"); let flag_only_uniques = call.has_flag("unique"); - // let metadata = input.metadata(); let mut uniq_values = input .into_iter() - .map(|item| { - item_mapper(ItemMapperState { + .map_while(|item| { + if ctrl_c_was_pressed(&ctrlc) { + return None; + } + Some(item_mapper(ItemMapperState { item, flag_ignore_case, - }) + })) }) .fold(Vec::::new(), |mut counter, item| { match counter diff --git a/crates/nu-command/src/input_handler.rs b/crates/nu-command/src/input_handler.rs index 342c00bf60..c9694bcfa9 100644 --- a/crates/nu-command/src/input_handler.rs +++ b/crates/nu-command/src/input_handler.rs @@ -1,6 +1,6 @@ use nu_protocol::ast::CellPath; use nu_protocol::{PipelineData, ShellError, Span, Value}; -use std::sync::atomic::AtomicBool; +use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::Arc; pub trait CmdArgument { @@ -71,3 +71,12 @@ where } } } + +// Helper method to avoid boilerplate every time we check ctrl+c +pub fn ctrl_c_was_pressed(ctrlc: &Option>) -> bool { + if let Some(ctrlc) = ctrlc { + ctrlc.load(Ordering::SeqCst) + } else { + false + } +}