mirror of
https://github.com/nushell/nushell
synced 2024-12-27 05:23:11 +00:00
Add helper method to check whether ctrl+c was pressed, adopt it (#7482)
I've been working on streaming and pipeline interruption lately. It was bothering me that checking ctrl+c (something we want to do often) always requires a bunch of boilerplate like: ```rust use std::sync::atomic::Ordering; if let Some(ctrlc) = &engine_state.ctrlc { if ctrlc.load(Ordering::SeqCst) { ... ``` I added a helper method to cut that down to: ```rust if nu_utils::ctrl_c::was_pressed(&engine_state.ctrlc) { ... ```
This commit is contained in:
parent
33aea56ccd
commit
e215fbbd08
16 changed files with 69 additions and 137 deletions
|
@ -1,5 +1,3 @@
|
|||
use std::sync::atomic::Ordering;
|
||||
|
||||
use nu_engine::{eval_block, CallExt};
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Block, Command, EngineState, Stack};
|
||||
|
@ -44,10 +42,8 @@ impl Command for Loop {
|
|||
let block: Block = call.req(engine_state, stack, 0)?;
|
||||
|
||||
loop {
|
||||
if let Some(ctrlc) = &engine_state.ctrlc {
|
||||
if ctrlc.load(Ordering::SeqCst) {
|
||||
break;
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(&engine_state.ctrlc) {
|
||||
break;
|
||||
}
|
||||
|
||||
let block = engine_state.get_block(block.block_id);
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use std::sync::atomic::Ordering;
|
||||
|
||||
use nu_engine::{eval_block, eval_expression, CallExt};
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Block, Command, EngineState, Stack};
|
||||
|
@ -48,10 +46,8 @@ impl Command for While {
|
|||
let block: Block = call.req(engine_state, stack, 1)?;
|
||||
|
||||
loop {
|
||||
if let Some(ctrlc) = &engine_state.ctrlc {
|
||||
if ctrlc.load(Ordering::SeqCst) {
|
||||
break;
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(&engine_state.ctrlc) {
|
||||
break;
|
||||
}
|
||||
|
||||
let result = eval_expression(engine_state, stack, cond)?;
|
||||
|
|
|
@ -10,10 +10,7 @@ use std::{
|
|||
fs::File,
|
||||
io::Read,
|
||||
path::{Path, PathBuf},
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
},
|
||||
sync::{atomic::AtomicBool, Arc},
|
||||
};
|
||||
|
||||
const SQLITE_MAGIC_BYTES: &[u8] = "SQLite format 3\0".as_bytes();
|
||||
|
@ -399,14 +396,12 @@ fn prepared_statement_to_nu_list(
|
|||
let mut row_values = vec![];
|
||||
|
||||
for row_result in row_results {
|
||||
if let Some(ctrlc) = &ctrlc {
|
||||
if ctrlc.load(Ordering::SeqCst) {
|
||||
// return whatever we have so far, let the caller decide whether to use it
|
||||
return Ok(Value::List {
|
||||
vals: row_values,
|
||||
span: call_span,
|
||||
});
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(&ctrlc) {
|
||||
// return whatever we have so far, let the caller decide whether to use it
|
||||
return Ok(Value::List {
|
||||
vals: row_values,
|
||||
span: call_span,
|
||||
});
|
||||
}
|
||||
|
||||
if let Ok(row_value) = row_result {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use std::path::PathBuf;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::mpsc::{channel, RecvTimeoutError};
|
||||
use std::time::Duration;
|
||||
|
||||
|
@ -252,10 +251,8 @@ impl Command for Watch {
|
|||
}
|
||||
Err(RecvTimeoutError::Timeout) => {}
|
||||
}
|
||||
if let Some(ctrlc) = ctrlc_ref {
|
||||
if ctrlc.load(Ordering::SeqCst) {
|
||||
break;
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(ctrlc_ref) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use std::sync::atomic::Ordering;
|
||||
|
||||
use nu_engine::{eval_block, CallExt};
|
||||
|
||||
use nu_protocol::ast::Call;
|
||||
|
@ -217,10 +215,8 @@ impl Command for Reduce {
|
|||
)?
|
||||
.into_value(span);
|
||||
|
||||
if let Some(ctrlc) = &ctrlc {
|
||||
if ctrlc.load(Ordering::SeqCst) {
|
||||
break;
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(&ctrlc) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use crate::input_handler::ctrl_c_was_pressed;
|
||||
use nu_protocol::ast::Call;
|
||||
use nu_protocol::engine::{Command, EngineState, Stack};
|
||||
use nu_protocol::{
|
||||
|
@ -231,7 +230,7 @@ pub fn uniq(
|
|||
let mut uniq_values = input
|
||||
.into_iter()
|
||||
.map_while(|item| {
|
||||
if ctrl_c_was_pressed(&ctrlc) {
|
||||
if nu_utils::ctrl_c::was_pressed(&ctrlc) {
|
||||
return None;
|
||||
}
|
||||
Some(item_mapper(ItemMapperState {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use nu_protocol::ast::CellPath;
|
||||
use nu_protocol::{PipelineData, ShellError, Span, Value};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait CmdArgument {
|
||||
|
@ -71,12 +71,3 @@ where
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Helper method to avoid boilerplate every time we check ctrl+c
|
||||
pub fn ctrl_c_was_pressed(ctrlc: &Option<Arc<AtomicBool>>) -> bool {
|
||||
if let Some(ctrlc) = ctrlc {
|
||||
ctrlc.load(Ordering::SeqCst)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use filesize::file_real_size_fast;
|
|||
use nu_glob::Pattern;
|
||||
use nu_protocol::{ShellError, Span, Value};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -106,13 +106,8 @@ impl DirInfo {
|
|||
match std::fs::read_dir(&s.path) {
|
||||
Ok(d) => {
|
||||
for f in d {
|
||||
match ctrl_c {
|
||||
Some(ref cc) => {
|
||||
if cc.load(Ordering::SeqCst) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
None => continue,
|
||||
if nu_utils::ctrl_c::was_pressed(&ctrl_c) {
|
||||
break;
|
||||
}
|
||||
|
||||
match f {
|
||||
|
|
|
@ -6,7 +6,6 @@ use nu_protocol::{
|
|||
Type, Value,
|
||||
};
|
||||
use std::{
|
||||
sync::atomic::Ordering,
|
||||
thread,
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
|
@ -62,10 +61,8 @@ impl Command for Sleep {
|
|||
break;
|
||||
}
|
||||
|
||||
if let Some(ctrlc) = ctrlc_ref {
|
||||
if ctrlc.load(Ordering::SeqCst) {
|
||||
break;
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(ctrlc_ref) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ use std::collections::HashMap;
|
|||
use std::io::{BufRead, BufReader, Read, Write};
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Command as CommandSys, Stdio};
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::mpsc::{self, SyncSender};
|
||||
use std::sync::Arc;
|
||||
|
||||
|
@ -745,10 +745,8 @@ fn read_and_redirect_message<R>(
|
|||
let length = bytes.len();
|
||||
buf_read.consume(length);
|
||||
|
||||
if let Some(ctrlc) = &ctrlc {
|
||||
if ctrlc.load(Ordering::SeqCst) {
|
||||
break;
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(&ctrlc) {
|
||||
break;
|
||||
}
|
||||
|
||||
match sender.send(bytes) {
|
||||
|
|
|
@ -12,12 +12,7 @@ use nu_table::{string_width, Alignment, Table as NuTable, TableConfig, TableThem
|
|||
use nu_utils::get_ls_colors;
|
||||
use std::sync::Arc;
|
||||
use std::time::Instant;
|
||||
use std::{
|
||||
cmp::max,
|
||||
collections::HashMap,
|
||||
path::PathBuf,
|
||||
sync::atomic::{AtomicBool, Ordering},
|
||||
};
|
||||
use std::{cmp::max, collections::HashMap, path::PathBuf, sync::atomic::AtomicBool};
|
||||
use terminal_size::{Height, Width};
|
||||
use url::Url;
|
||||
|
||||
|
@ -304,13 +299,8 @@ fn handle_table_command(
|
|||
|
||||
let result = strip_output_color(result, config);
|
||||
|
||||
let ctrl_c_was_triggered = || match &ctrlc {
|
||||
Some(ctrlc) => ctrlc.load(Ordering::SeqCst),
|
||||
None => false,
|
||||
};
|
||||
|
||||
let result = result.unwrap_or_else(|| {
|
||||
if ctrl_c_was_triggered() {
|
||||
if nu_utils::ctrl_c::was_pressed(&ctrlc) {
|
||||
"".into()
|
||||
} else {
|
||||
// assume this failed because the table was too wide
|
||||
|
@ -397,11 +387,8 @@ fn build_general_table2(
|
|||
) -> Result<Option<String>, ShellError> {
|
||||
let mut data = Vec::with_capacity(vals.len());
|
||||
for (column, value) in cols.into_iter().zip(vals.into_iter()) {
|
||||
// handle CTRLC event
|
||||
if let Some(ctrlc) = &ctrlc {
|
||||
if ctrlc.load(Ordering::SeqCst) {
|
||||
return Ok(None);
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(&ctrlc) {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let row = vec![
|
||||
|
@ -460,11 +447,8 @@ fn build_expanded_table(
|
|||
|
||||
let mut data = Vec::with_capacity(cols.len());
|
||||
for (key, value) in cols.into_iter().zip(vals) {
|
||||
// handle CTRLC event
|
||||
if let Some(ctrlc) = &ctrlc {
|
||||
if ctrlc.load(Ordering::SeqCst) {
|
||||
return Ok(None);
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(&ctrlc) {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let is_limited = matches!(expand_limit, Some(0));
|
||||
|
@ -810,10 +794,8 @@ fn convert_to_table(
|
|||
};
|
||||
|
||||
for (row_num, item) in input.enumerate() {
|
||||
if let Some(ctrlc) = &ctrlc {
|
||||
if ctrlc.load(Ordering::SeqCst) {
|
||||
return Ok(None);
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(&ctrlc) {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
if let Value::Error { error } = item {
|
||||
|
@ -925,10 +907,8 @@ fn convert_to_table2<'a>(
|
|||
}
|
||||
|
||||
for (row, item) in input.clone().into_iter().enumerate() {
|
||||
if let Some(ctrlc) = &ctrlc {
|
||||
if ctrlc.load(Ordering::SeqCst) {
|
||||
return Ok(None);
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(&ctrlc) {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
if let Value::Error { error } = item {
|
||||
|
@ -960,10 +940,8 @@ fn convert_to_table2<'a>(
|
|||
|
||||
if !with_header {
|
||||
for (row, item) in input.into_iter().enumerate() {
|
||||
if let Some(ctrlc) = &ctrlc {
|
||||
if ctrlc.load(Ordering::SeqCst) {
|
||||
return Ok(None);
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(&ctrlc) {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
if let Value::Error { error } = item {
|
||||
|
@ -1019,10 +997,8 @@ fn convert_to_table2<'a>(
|
|||
data[0].push(NuTable::create_cell(&header, header_style(color_hm)));
|
||||
|
||||
for (row, item) in input.clone().into_iter().enumerate() {
|
||||
if let Some(ctrlc) = &ctrlc {
|
||||
if ctrlc.load(Ordering::SeqCst) {
|
||||
return Ok(None);
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(&ctrlc) {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
if let Value::Error { error } = item {
|
||||
|
@ -1059,10 +1035,8 @@ fn convert_to_table2<'a>(
|
|||
column_width = string_width(&header);
|
||||
|
||||
for (row, item) in input.clone().into_iter().enumerate() {
|
||||
if let Some(ctrlc) = &ctrlc {
|
||||
if ctrlc.load(Ordering::SeqCst) {
|
||||
return Ok(None);
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(&ctrlc) {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let value = create_table2_entry_basic(item, &header, head, config, color_hm);
|
||||
|
@ -1086,10 +1060,8 @@ fn convert_to_table2<'a>(
|
|||
column_width = string_width(&header);
|
||||
|
||||
for (row, item) in input.clone().into_iter().enumerate() {
|
||||
if let Some(ctrlc) = &ctrlc {
|
||||
if ctrlc.load(Ordering::SeqCst) {
|
||||
return Ok(None);
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(&ctrlc) {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let value = create_table2_entry_basic(item, &header, head, config, color_hm);
|
||||
|
@ -1593,10 +1565,8 @@ impl Iterator for PagingTableCreator {
|
|||
break;
|
||||
}
|
||||
|
||||
if let Some(ctrlc) = &self.ctrlc {
|
||||
if ctrlc.load(Ordering::SeqCst) {
|
||||
break;
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(&self.ctrlc) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -31,10 +31,8 @@ pub fn eval_call(
|
|||
call: &Call,
|
||||
input: PipelineData,
|
||||
) -> Result<PipelineData, ShellError> {
|
||||
if let Some(ctrlc) = &engine_state.ctrlc {
|
||||
if ctrlc.load(core::sync::atomic::Ordering::SeqCst) {
|
||||
return Ok(Value::Nothing { span: call.head }.into_pipeline_data());
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(&engine_state.ctrlc) {
|
||||
return Ok(Value::Nothing { span: call.head }.into_pipeline_data());
|
||||
}
|
||||
let decl = engine_state.get_decl(call.decl_id);
|
||||
|
||||
|
|
|
@ -203,10 +203,8 @@ impl Iterator for RangeIterator {
|
|||
return None;
|
||||
}
|
||||
|
||||
if let Some(ctrlc) = &self.ctrlc {
|
||||
if ctrlc.load(core::sync::atomic::Ordering::SeqCst) {
|
||||
return None;
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(&self.ctrlc) {
|
||||
return None;
|
||||
}
|
||||
|
||||
let ordering = if matches!(self.end, Value::Nothing { .. }) {
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
use crate::*;
|
||||
use std::{
|
||||
fmt::Debug,
|
||||
sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
},
|
||||
sync::{atomic::AtomicBool, Arc},
|
||||
};
|
||||
|
||||
pub struct RawStream {
|
||||
|
@ -77,10 +74,8 @@ impl Iterator for RawStream {
|
|||
type Item = Result<Value, ShellError>;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some(ctrlc) = &self.ctrlc {
|
||||
if ctrlc.load(Ordering::SeqCst) {
|
||||
return None;
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(&self.ctrlc) {
|
||||
return None;
|
||||
}
|
||||
|
||||
// If we know we're already binary, just output that
|
||||
|
@ -223,12 +218,8 @@ impl Iterator for ListStream {
|
|||
type Item = Value;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some(ctrlc) = &self.ctrlc {
|
||||
if ctrlc.load(Ordering::SeqCst) {
|
||||
None
|
||||
} else {
|
||||
self.stream.next()
|
||||
}
|
||||
if nu_utils::ctrl_c::was_pressed(&self.ctrlc) {
|
||||
None
|
||||
} else {
|
||||
self.stream.next()
|
||||
}
|
||||
|
|
13
crates/nu-utils/src/ctrl_c.rs
Normal file
13
crates/nu-utils/src/ctrl_c.rs
Normal file
|
@ -0,0 +1,13 @@
|
|||
use std::sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
Arc,
|
||||
};
|
||||
|
||||
/// Returns true if Nu has received a SIGINT signal / ctrl+c event
|
||||
pub fn was_pressed(ctrlc: &Option<Arc<AtomicBool>>) -> bool {
|
||||
if let Some(ctrlc) = ctrlc {
|
||||
ctrlc.load(Ordering::SeqCst)
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
|
@ -1,7 +1,9 @@
|
|||
pub mod ctrl_c;
|
||||
mod deansi;
|
||||
pub mod locale;
|
||||
pub mod utils;
|
||||
|
||||
pub use ctrl_c::was_pressed;
|
||||
pub use locale::get_system_locale;
|
||||
pub use utils::{
|
||||
enable_vt_processing, get_default_config, get_default_env, get_ls_colors,
|
||||
|
|
Loading…
Reference in a new issue