mirror of
https://github.com/nushell/nushell.git
synced 2025-08-10 06:58:36 +02:00
Add and use new Signals
struct (#13314)
# Description This PR introduces a new `Signals` struct to replace our adhoc passing around of `ctrlc: Option<Arc<AtomicBool>>`. Doing so has a few benefits: - We can better enforce when/where resetting or triggering an interrupt is allowed. - Consolidates `nu_utils::ctrl_c::was_pressed` and other ad-hoc re-implementations into a single place: `Signals::check`. - This allows us to add other types of signals later if we want. E.g., exiting or suspension. - Similarly, we can more easily change the underlying implementation if we need to in the future. - Places that used to have a `ctrlc` of `None` now use `Signals::empty()`, so we can double check these usages for correctness in the future.
This commit is contained in:
@ -1,11 +1,8 @@
|
||||
use nu_ansi_term::*;
|
||||
use nu_engine::command_prelude::*;
|
||||
use nu_protocol::engine::StateWorkingSet;
|
||||
use nu_protocol::{engine::StateWorkingSet, Signals};
|
||||
use once_cell::sync::Lazy;
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
sync::{atomic::AtomicBool, Arc},
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct AnsiCommand;
|
||||
@ -657,10 +654,13 @@ Operating system commands:
|
||||
let escape: bool = call.has_flag(engine_state, stack, "escape")?;
|
||||
let osc: bool = call.has_flag(engine_state, stack, "osc")?;
|
||||
let use_ansi_coloring = engine_state.get_config().use_ansi_coloring;
|
||||
let ctrlc = engine_state.ctrlc.clone();
|
||||
|
||||
if list {
|
||||
return Ok(generate_ansi_code_list(ctrlc, call.head, use_ansi_coloring));
|
||||
return Ok(generate_ansi_code_list(
|
||||
engine_state.signals().clone(),
|
||||
call.head,
|
||||
use_ansi_coloring,
|
||||
));
|
||||
}
|
||||
|
||||
// The code can now be one of the ansi abbreviations like green_bold
|
||||
@ -691,10 +691,13 @@ Operating system commands:
|
||||
let escape: bool = call.has_flag_const(working_set, "escape")?;
|
||||
let osc: bool = call.has_flag_const(working_set, "osc")?;
|
||||
let use_ansi_coloring = working_set.get_config().use_ansi_coloring;
|
||||
let ctrlc = working_set.permanent().ctrlc.clone();
|
||||
|
||||
if list {
|
||||
return Ok(generate_ansi_code_list(ctrlc, call.head, use_ansi_coloring));
|
||||
return Ok(generate_ansi_code_list(
|
||||
working_set.permanent().signals().clone(),
|
||||
call.head,
|
||||
use_ansi_coloring,
|
||||
));
|
||||
}
|
||||
|
||||
// The code can now be one of the ansi abbreviations like green_bold
|
||||
@ -827,7 +830,7 @@ pub fn str_to_ansi(s: &str) -> Option<String> {
|
||||
}
|
||||
|
||||
fn generate_ansi_code_list(
|
||||
ctrlc: Option<Arc<AtomicBool>>,
|
||||
signals: Signals,
|
||||
call_span: Span,
|
||||
use_ansi_coloring: bool,
|
||||
) -> PipelineData {
|
||||
@ -862,7 +865,7 @@ fn generate_ansi_code_list(
|
||||
|
||||
Value::record(record, call_span)
|
||||
})
|
||||
.into_pipeline_data(call_span, ctrlc)
|
||||
.into_pipeline_data(call_span, signals.clone())
|
||||
}
|
||||
|
||||
fn build_ansi_hashmap(v: &[AnsiCode]) -> HashMap<&str, &str> {
|
||||
|
@ -91,12 +91,12 @@ fn operate(
|
||||
if column_paths.is_empty() {
|
||||
input.map(
|
||||
move |v| process_value(&v, text.as_deref()),
|
||||
engine_state.ctrlc.clone(),
|
||||
engine_state.signals(),
|
||||
)
|
||||
} else {
|
||||
input.map(
|
||||
move |v| process_each_path(v, &column_paths, text.as_deref(), command_span),
|
||||
engine_state.ctrlc.clone(),
|
||||
engine_state.signals(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ impl Command for SubCommand {
|
||||
cell_paths,
|
||||
config: config.clone(),
|
||||
};
|
||||
operate(action, args, input, call.head, engine_state.ctrlc.clone())
|
||||
operate(action, args, input, call.head, engine_state.signals())
|
||||
}
|
||||
|
||||
fn examples(&self) -> Vec<Example> {
|
||||
|
@ -1,10 +1,7 @@
|
||||
use filesize::file_real_size_fast;
|
||||
use nu_glob::Pattern;
|
||||
use nu_protocol::{record, ShellError, Span, Value};
|
||||
use std::{
|
||||
path::PathBuf,
|
||||
sync::{atomic::AtomicBool, Arc},
|
||||
};
|
||||
use nu_protocol::{record, ShellError, Signals, Span, Value};
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DirBuilder {
|
||||
@ -82,8 +79,9 @@ impl DirInfo {
|
||||
path: impl Into<PathBuf>,
|
||||
params: &DirBuilder,
|
||||
depth: Option<u64>,
|
||||
ctrl_c: Option<Arc<AtomicBool>>,
|
||||
) -> Self {
|
||||
span: Span,
|
||||
signals: &Signals,
|
||||
) -> Result<Self, ShellError> {
|
||||
let path = path.into();
|
||||
|
||||
let mut s = Self {
|
||||
@ -107,14 +105,12 @@ impl DirInfo {
|
||||
match std::fs::read_dir(&s.path) {
|
||||
Ok(d) => {
|
||||
for f in d {
|
||||
if nu_utils::ctrl_c::was_pressed(&ctrl_c) {
|
||||
break;
|
||||
}
|
||||
signals.check(span)?;
|
||||
|
||||
match f {
|
||||
Ok(i) => match i.file_type() {
|
||||
Ok(t) if t.is_dir() => {
|
||||
s = s.add_dir(i.path(), depth, params, ctrl_c.clone())
|
||||
s = s.add_dir(i.path(), depth, params, span, signals)?
|
||||
}
|
||||
Ok(_t) => s = s.add_file(i.path(), params),
|
||||
Err(e) => s = s.add_error(e.into()),
|
||||
@ -125,7 +121,7 @@ impl DirInfo {
|
||||
}
|
||||
Err(e) => s = s.add_error(e.into()),
|
||||
}
|
||||
s
|
||||
Ok(s)
|
||||
}
|
||||
|
||||
fn add_dir(
|
||||
@ -133,21 +129,22 @@ impl DirInfo {
|
||||
path: impl Into<PathBuf>,
|
||||
mut depth: Option<u64>,
|
||||
params: &DirBuilder,
|
||||
ctrl_c: Option<Arc<AtomicBool>>,
|
||||
) -> Self {
|
||||
span: Span,
|
||||
signals: &Signals,
|
||||
) -> Result<Self, ShellError> {
|
||||
if let Some(current) = depth {
|
||||
if let Some(new) = current.checked_sub(1) {
|
||||
depth = Some(new);
|
||||
} else {
|
||||
return self;
|
||||
return Ok(self);
|
||||
}
|
||||
}
|
||||
|
||||
let d = DirInfo::new(path, params, depth, ctrl_c);
|
||||
let d = DirInfo::new(path, params, depth, span, signals)?;
|
||||
self.size += d.size;
|
||||
self.blocks += d.blocks;
|
||||
self.dirs.push(d);
|
||||
self
|
||||
Ok(self)
|
||||
}
|
||||
|
||||
fn add_file(mut self, f: impl Into<PathBuf>, params: &DirBuilder) -> Self {
|
||||
|
@ -56,12 +56,7 @@ impl Command for Sleep {
|
||||
break;
|
||||
}
|
||||
thread::sleep(CTRL_C_CHECK_INTERVAL.min(time_until_deadline));
|
||||
// exit early if Ctrl+C was pressed
|
||||
if nu_utils::ctrl_c::was_pressed(&engine_state.ctrlc) {
|
||||
return Err(ShellError::InterruptedByUser {
|
||||
span: Some(call.head),
|
||||
});
|
||||
}
|
||||
engine_state.signals().check(call.head)?;
|
||||
}
|
||||
|
||||
Ok(Value::nothing(call.head).into_pipeline_data())
|
||||
|
Reference in New Issue
Block a user