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:
Ian Manske
2024-07-07 22:29:01 +00:00
committed by GitHub
parent c6b6b1b7a8
commit 399a7c8836
246 changed files with 1332 additions and 1234 deletions

View File

@ -1,5 +1,5 @@
use nu_engine::{command_prelude::*, get_eval_block, get_eval_expression};
use nu_protocol::engine::CommandType;
use nu_protocol::{engine::CommandType, Signals};
#[derive(Clone)]
pub struct For;
@ -72,7 +72,6 @@ impl Command for For {
let value = eval_expression(engine_state, stack, keyword_expr)?;
let ctrlc = engine_state.ctrlc.clone();
let engine_state = engine_state.clone();
let block = engine_state.get_block(block_id);
@ -82,9 +81,7 @@ impl Command for For {
match value {
Value::List { vals, .. } => {
for x in vals.into_iter() {
if nu_utils::ctrl_c::was_pressed(&ctrlc) {
break;
}
engine_state.signals().check(head)?;
// with_env() is used here to ensure that each iteration uses
// a different set of environment variables.
@ -116,7 +113,8 @@ impl Command for For {
}
}
Value::Range { val, .. } => {
for x in val.into_range_iter(span, ctrlc) {
for x in val.into_range_iter(span, Signals::empty()) {
engine_state.signals().check(head)?;
stack.add_var(var_id, x);
match eval_block(&engine_state, stack, block, PipelineData::empty()) {

View File

@ -37,6 +37,7 @@ impl Command for Loop {
call: &Call,
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let block_id = call
.positional_nth(0)
.expect("checked through parser")
@ -49,9 +50,7 @@ impl Command for Loop {
let stack = &mut stack.push_redirection(None, None);
loop {
if nu_utils::ctrl_c::was_pressed(&engine_state.ctrlc) {
break;
}
engine_state.signals().check(head)?;
match eval_block(engine_state, stack, block, PipelineData::empty()) {
Err(ShellError::Break { .. }) => {

View File

@ -46,6 +46,7 @@ impl Command for While {
call: &Call,
_input: PipelineData,
) -> Result<PipelineData, ShellError> {
let head = call.head;
let cond = call.positional_nth(0).expect("checked through parser");
let block_id = call
.positional_nth(1)
@ -59,9 +60,7 @@ impl Command for While {
let stack = &mut stack.push_redirection(None, None);
loop {
if nu_utils::ctrl_c::was_pressed(&engine_state.ctrlc) {
break;
}
engine_state.signals().check(head)?;
let result = eval_expression(engine_state, stack, cond)?;