mirror of
https://github.com/nushell/nushell.git
synced 2025-08-09 07:35:42 +02:00
Check for interrupt before each IR instruction (#16134)
# Description Fixes #15308. Surprisingly, I can't find any more issues that bring this up. This PR adds a check for interrupt before evaluating each IR instruction. This makes it possible to ctrl-c out of things that were difficult/impossible previously, like: ```nushell loop {} ``` @devyn also [mentioned previously](https://discord.com/channels/601130461678272522/615329862395101194/1268674828492083327) that this might be a feasible option, but mentioned some performance concerns. I did some benchmarking previously but it turns out tango isn't the greatest for this. I don't have hard numbers anymore but based on some experimenting I shared in the Discord it seems like no experimental option and limiting this to specific instructions should keep the performance impact minimal. <details> <summary>Old benchmarking info</summary> I did some benchmarks against main. It seems like most benchmarks are between 1-6% slower, with some oddball exceptions. The worst case seems to a giant loop, which makes sense since it's mostly just jumping back to the beginning, meaning we hit the check over and over again. With `bench --pretty -n 100 { for i in 0..1000000 { 1 } }`, it seems like the `ir-interrupt` branch is ~10% slower for this stress case: ``` main: 94ms 323µs 29ns +/- 1ms 291µs 759ns ir-interrupt: 103ms 54µs 708ns +/- 1ms 606µs 571ns (103ms + 54µs + 708ns) / (94ms + 323µs + 29ns) = 1.0925720801438639 ``` The performance numbers here aren't great, but they're not terrible either, and I think the usability improvement is probably worth it here. <details> <summary>Tango benchmarks</summary> ``` load_standard_lib [ 2.8 ms ... 2.9 ms ] +3.53%* record_create_1 [ 101.8 us ... 107.0 us ] +5.12%* record_create_10 [ 132.3 us ... 135.6 us ] +2.48%* record_create_100 [ 349.7 us ... 354.6 us ] +1.39%* record_create_1000 [ 3.7 ms ... 3.6 ms ] -1.30% record_flat_access_1 [ 94.8 us ... 99.9 us ] +5.35%* record_flat_access_10 [ 96.2 us ... 101.3 us ] +5.33%* record_flat_access_100 [ 106.0 us ... 111.4 us ] +5.07%* record_flat_access_1000 [ 203.0 us ... 208.5 us ] +2.69% record_nested_access_1 [ 95.3 us ... 100.1 us ] +5.03%* record_nested_access_2 [ 98.4 us ... 104.6 us ] +6.26%* record_nested_access_4 [ 100.8 us ... 105.4 us ] +4.56%* record_nested_access_8 [ 104.7 us ... 108.1 us ] +3.23% record_nested_access_16 [ 110.6 us ... 115.8 us ] +4.71%* record_nested_access_32 [ 119.0 us ... 124.0 us ] +4.20%* record_nested_access_64 [ 137.4 us ... 142.2 us ] +3.47%* record_nested_access_128 [ 176.7 us ... 181.8 us ] +2.87%* record_insert_1_1 [ 106.2 us ... 111.9 us ] +5.35%* record_insert_10_1 [ 111.2 us ... 116.0 us ] +4.28%* record_insert_100_1 [ 134.3 us ... 139.8 us ] +4.06%* record_insert_1000_1 [ 387.8 us ... 417.1 us ] +7.55% record_insert_1_10 [ 162.9 us ... 171.5 us ] +5.23%* record_insert_10_10 [ 159.5 us ... 166.2 us ] +4.23%* record_insert_100_10 [ 183.3 us ... 190.7 us ] +4.04%* record_insert_1000_10 [ 411.7 us ... 418.7 us ] +1.71%* table_create_1 [ 117.2 us ... 120.3 us ] +2.66% table_create_10 [ 144.9 us ... 152.2 us ] +5.02%* table_create_100 [ 476.0 us ... 484.8 us ] +1.86%* table_create_1000 [ 3.7 ms ... 3.7 ms ] +1.55% table_get_1 [ 121.6 us ... 127.0 us ] +4.40%* table_get_10 [ 112.1 us ... 117.4 us ] +4.71%* table_get_100 [ 124.0 us ... 129.5 us ] +4.41%* table_get_1000 [ 229.9 us ... 245.5 us ] +6.75%* table_select_1 [ 111.1 us ... 115.6 us ] +4.03%* table_select_10 [ 112.1 us ... 118.4 us ] +5.65%* table_select_100 [ 142.2 us ... 147.2 us ] +3.53%* table_select_1000 [ 383.5 us ... 370.3 us ] -3.43%* table_insert_row_1_1 [ 122.5 us ... 127.8 us ] +4.35%* table_insert_row_10_1 [ 123.6 us ... 128.6 us ] +3.99%* table_insert_row_100_1 [ 124.9 us ... 131.2 us ] +5.05%* table_insert_row_1000_1 [ 177.3 us ... 182.7 us ] +3.07%* table_insert_row_1_10 [ 225.7 us ... 234.5 us ] +3.90%* table_insert_row_10_10 [ 229.2 us ... 235.4 us ] +2.69%* table_insert_row_100_10 [ 253.3 us ... 257.6 us ] +1.69% table_insert_row_1000_10 [ 311.1 us ... 318.3 us ] +2.32%* table_insert_col_1_1 [ 107.6 us ... 113.3 us ] +5.35%* table_insert_col_10_1 [ 109.6 us ... 115.3 us ] +5.27%* table_insert_col_100_1 [ 155.5 us ... 159.8 us ] +2.71%* table_insert_col_1000_1 [ 476.6 us ... 480.8 us ] +0.88%* table_insert_col_1_10 [ 167.7 us ... 177.4 us ] +5.75% table_insert_col_10_10 [ 178.5 us ... 194.8 us ] +9.16%* table_insert_col_100_10 [ 314.4 us ... 322.3 us ] +2.53%* table_insert_col_1000_10 [ 1.7 ms ... 1.7 ms ] +1.35%* eval_interleave_100 [ 485.8 us ... 506.5 us ] +4.27% eval_interleave_1000 [ 3.3 ms ... 3.2 ms ] -1.51% eval_interleave_10000 [ 31.5 ms ... 31.0 ms ] -1.80% eval_interleave_with_interrupt_100 [ 473.2 us ... 479.6 us ] +1.35% eval_interleave_with_interrupt_1000 [ 3.2 ms ... 3.2 ms ] -1.26% eval_interleave_with_interrupt_10000 [ 32.3 ms ... 31.1 ms ] -3.81% eval_for_1 [ 124.4 us ... 130.1 us ] +4.60%* eval_for_10 [ 124.4 us ... 130.3 us ] +4.80%* eval_for_100 [ 134.5 us ... 141.5 us ] +5.18%* eval_for_1000 [ 222.7 us ... 244.0 us ] +9.59%* eval_for_10000 [ 1.0 ms ... 1.2 ms ] +13.86%* eval_each_1 [ 146.9 us ... 153.0 us ] +4.15%* eval_each_10 [ 152.3 us ... 158.8 us ] +4.26%* eval_each_100 [ 169.3 us ... 175.6 us ] +3.76%* eval_each_1000 [ 346.8 us ... 357.4 us ] +3.06%* eval_each_10000 [ 2.1 ms ... 2.2 ms ] +2.37%* eval_par_each_1 [ 194.3 us ... 203.5 us ] +4.73%* eval_par_each_10 [ 186.4 us ... 193.1 us ] +3.59%* eval_par_each_100 [ 213.5 us ... 222.2 us ] +4.08%* eval_par_each_1000 [ 433.4 us ... 437.4 us ] +0.93% eval_par_each_10000 [ 2.4 ms ... 2.4 ms ] -0.40% eval_default_config [ 406.3 us ... 414.9 us ] +2.12%* eval_default_env [ 475.7 us ... 495.1 us ] +4.08%* encode_json_100_5 [ 132.7 us ... 128.9 us ] -2.88%* encode_json_10000_15 [ 35.5 ms ... 34.0 ms ] -4.15%* encode_msgpack_100_5 [ 85.0 us ... 83.9 us ] -1.20%* encode_msgpack_10000_15 [ 22.2 ms ... 21.7 ms ] -2.17%* decode_json_100_5 [ 431.3 us ... 421.0 us ] -2.40%* decode_json_10000_15 [ 119.7 ms ... 117.6 ms ] -1.76%* decode_msgpack_100_5 [ 160.6 us ... 151.1 us ] -5.90%* decode_msgpack_10000_15 [ 44.0 ms ... 43.1 ms ] -2.12%* ``` </details> </details> # User-Facing Changes * It should be possible to ctrl-c in situations where it was not previously possible # Tests + Formatting N/A # After Submitting N/A
This commit is contained in:
@ -241,7 +241,7 @@ fn insert_in_transaction(
|
|||||||
let tx = table.try_init(&first_val)?;
|
let tx = table.try_init(&first_val)?;
|
||||||
|
|
||||||
for stream_value in stream {
|
for stream_value in stream {
|
||||||
if let Err(err) = signals.check(span) {
|
if let Err(err) = signals.check(&span) {
|
||||||
tx.rollback().map_err(|e| ShellError::GenericError {
|
tx.rollback().map_err(|e| ShellError::GenericError {
|
||||||
error: "Failed to rollback SQLite transaction".into(),
|
error: "Failed to rollback SQLite transaction".into(),
|
||||||
msg: e.to_string(),
|
msg: e.to_string(),
|
||||||
|
@ -588,7 +588,7 @@ fn prepared_statement_to_nu_list(
|
|||||||
let mut row_values = vec![];
|
let mut row_values = vec![];
|
||||||
|
|
||||||
for row_result in row_results {
|
for row_result in row_results {
|
||||||
signals.check(call_span)?;
|
signals.check(&call_span)?;
|
||||||
if let Ok(row_value) = row_result {
|
if let Ok(row_value) = row_result {
|
||||||
row_values.push(row_value);
|
row_values.push(row_value);
|
||||||
}
|
}
|
||||||
@ -614,7 +614,7 @@ fn prepared_statement_to_nu_list(
|
|||||||
let mut row_values = vec![];
|
let mut row_values = vec![];
|
||||||
|
|
||||||
for row_result in row_results {
|
for row_result in row_results {
|
||||||
signals.check(call_span)?;
|
signals.check(&call_span)?;
|
||||||
if let Ok(row_value) = row_result {
|
if let Ok(row_value) = row_result {
|
||||||
row_values.push(row_value);
|
row_values.push(row_value);
|
||||||
}
|
}
|
||||||
|
@ -329,7 +329,7 @@ fn glob_to_value(
|
|||||||
) -> ListStream {
|
) -> ListStream {
|
||||||
let map_signals = signals.clone();
|
let map_signals = signals.clone();
|
||||||
let result = glob_results.filter_map(move |entry| {
|
let result = glob_results.filter_map(move |entry| {
|
||||||
if let Err(err) = map_signals.check(span) {
|
if let Err(err) = map_signals.check(&span) {
|
||||||
return Some(Value::error(err, span));
|
return Some(Value::error(err, span));
|
||||||
};
|
};
|
||||||
let file_type = entry.file_type();
|
let file_type = entry.file_type();
|
||||||
|
@ -341,7 +341,7 @@ fn ls_for_one_pattern(
|
|||||||
|
|
||||||
let mut paths_peek = paths.peekable();
|
let mut paths_peek = paths.peekable();
|
||||||
let no_matches = paths_peek.peek().is_none();
|
let no_matches = paths_peek.peek().is_none();
|
||||||
signals.check(call_span)?;
|
signals.check(&call_span)?;
|
||||||
if no_matches {
|
if no_matches {
|
||||||
return Err(ShellError::GenericError {
|
return Err(ShellError::GenericError {
|
||||||
error: format!("No matches found for {:?}", path.item),
|
error: format!("No matches found for {:?}", path.item),
|
||||||
@ -979,14 +979,14 @@ fn read_dir(
|
|||||||
.read_dir()
|
.read_dir()
|
||||||
.map_err(|err| IoError::new(err, span, f.clone()))?
|
.map_err(|err| IoError::new(err, span, f.clone()))?
|
||||||
.map(move |d| {
|
.map(move |d| {
|
||||||
signals_clone.check(span)?;
|
signals_clone.check(&span)?;
|
||||||
d.map(|r| r.path())
|
d.map(|r| r.path())
|
||||||
.map_err(|err| IoError::new(err, span, f.clone()))
|
.map_err(|err| IoError::new(err, span, f.clone()))
|
||||||
.map_err(ShellError::from)
|
.map_err(ShellError::from)
|
||||||
});
|
});
|
||||||
if !use_threads {
|
if !use_threads {
|
||||||
let mut collected = items.collect::<Vec<_>>();
|
let mut collected = items.collect::<Vec<_>>();
|
||||||
signals.check(span)?;
|
signals.check(&span)?;
|
||||||
collected.sort_by(|a, b| match (a, b) {
|
collected.sort_by(|a, b| match (a, b) {
|
||||||
(Ok(a), Ok(b)) => a.cmp(b),
|
(Ok(a), Ok(b)) => a.cmp(b),
|
||||||
(Ok(_), Err(_)) => Ordering::Greater,
|
(Ok(_), Err(_)) => Ordering::Greater,
|
||||||
|
@ -454,7 +454,7 @@ fn rm(
|
|||||||
});
|
});
|
||||||
|
|
||||||
for result in iter {
|
for result in iter {
|
||||||
engine_state.signals().check(call.head)?;
|
engine_state.signals().check(&call.head)?;
|
||||||
match result {
|
match result {
|
||||||
Ok(None) => {}
|
Ok(None) => {}
|
||||||
Ok(Some(msg)) => eprintln!("{msg}"),
|
Ok(Some(msg)) => eprintln!("{msg}"),
|
||||||
|
@ -543,7 +543,7 @@ fn stream_to_file(
|
|||||||
let mut reader = BufReader::new(source);
|
let mut reader = BufReader::new(source);
|
||||||
|
|
||||||
let res = loop {
|
let res = loop {
|
||||||
if let Err(err) = signals.check(span) {
|
if let Err(err) = signals.check(&span) {
|
||||||
bar.abandoned_msg("# Cancelled #".to_owned());
|
bar.abandoned_msg("# Cancelled #".to_owned());
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ impl Command for Last {
|
|||||||
let mut buf = VecDeque::new();
|
let mut buf = VecDeque::new();
|
||||||
|
|
||||||
for row in iterator {
|
for row in iterator {
|
||||||
engine_state.signals().check(head)?;
|
engine_state.signals().check(&head)?;
|
||||||
if buf.len() == rows {
|
if buf.len() == rows {
|
||||||
buf.pop_front();
|
buf.pop_front();
|
||||||
}
|
}
|
||||||
|
@ -119,7 +119,7 @@ impl Command for Reduce {
|
|||||||
let mut closure = ClosureEval::new(engine_state, stack, closure);
|
let mut closure = ClosureEval::new(engine_state, stack, closure);
|
||||||
|
|
||||||
for value in iter {
|
for value in iter {
|
||||||
engine_state.signals().check(head)?;
|
engine_state.signals().check(&head)?;
|
||||||
acc = closure
|
acc = closure
|
||||||
.add_arg(value)
|
.add_arg(value)
|
||||||
.add_arg(acc.clone())
|
.add_arg(acc.clone())
|
||||||
|
@ -31,7 +31,7 @@ pub fn boolean_fold(
|
|||||||
let mut closure = ClosureEval::new(engine_state, stack, closure);
|
let mut closure = ClosureEval::new(engine_state, stack, closure);
|
||||||
|
|
||||||
for value in input {
|
for value in input {
|
||||||
engine_state.signals().check(head)?;
|
engine_state.signals().check(&head)?;
|
||||||
let pred = closure.run_with_value(value)?.into_value(head)?.is_true();
|
let pred = closure.run_with_value(value)?.into_value(head)?.is_true();
|
||||||
|
|
||||||
if pred == accumulator {
|
if pred == accumulator {
|
||||||
|
@ -468,7 +468,7 @@ fn send_cancellable_request(
|
|||||||
|
|
||||||
// ...and poll the channel for responses
|
// ...and poll the channel for responses
|
||||||
loop {
|
loop {
|
||||||
signals.check(span)?;
|
signals.check(&span)?;
|
||||||
|
|
||||||
// 100ms wait time chosen arbitrarily
|
// 100ms wait time chosen arbitrarily
|
||||||
match rx.recv_timeout(Duration::from_millis(100)) {
|
match rx.recv_timeout(Duration::from_millis(100)) {
|
||||||
@ -526,7 +526,7 @@ fn send_cancellable_request_bytes(
|
|||||||
|
|
||||||
// ...and poll the channel for responses
|
// ...and poll the channel for responses
|
||||||
loop {
|
loop {
|
||||||
signals.check(span)?;
|
signals.check(&span)?;
|
||||||
|
|
||||||
// 100ms wait time chosen arbitrarily
|
// 100ms wait time chosen arbitrarily
|
||||||
match rx.recv_timeout(Duration::from_millis(100)) {
|
match rx.recv_timeout(Duration::from_millis(100)) {
|
||||||
|
@ -115,7 +115,7 @@ impl DirInfo {
|
|||||||
match std::fs::read_dir(&s.path) {
|
match std::fs::read_dir(&s.path) {
|
||||||
Ok(d) => {
|
Ok(d) => {
|
||||||
for f in d {
|
for f in d {
|
||||||
signals.check(span)?;
|
signals.check(&span)?;
|
||||||
|
|
||||||
match f {
|
match f {
|
||||||
Ok(i) => match i.file_type() {
|
Ok(i) => match i.file_type() {
|
||||||
|
@ -56,7 +56,7 @@ impl Command for Sleep {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
thread::sleep(CTRL_C_CHECK_INTERVAL.min(time_until_deadline));
|
thread::sleep(CTRL_C_CHECK_INTERVAL.min(time_until_deadline));
|
||||||
engine_state.signals().check(call.head)?;
|
engine_state.signals().check(&call.head)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Value::nothing(call.head).into_pipeline_data())
|
Ok(Value::nothing(call.head).into_pipeline_data())
|
||||||
|
@ -431,7 +431,7 @@ fn expand_glob(
|
|||||||
let mut result: Vec<OsString> = vec![];
|
let mut result: Vec<OsString> = vec![];
|
||||||
|
|
||||||
for m in matches {
|
for m in matches {
|
||||||
signals.check(span)?;
|
signals.check(&span)?;
|
||||||
if let Ok(arg) = m {
|
if let Ok(arg) = m {
|
||||||
let arg = resolve_globbed_path_to_cwd_relative(arg, prefix.as_ref(), cwd);
|
let arg = resolve_globbed_path_to_cwd_relative(arg, prefix.as_ref(), cwd);
|
||||||
result.push(arg.into());
|
result.push(arg.into());
|
||||||
|
@ -347,7 +347,9 @@ impl BlockBuilder {
|
|||||||
/// Deallocate a register and set it to `Empty`, if it is allocated
|
/// Deallocate a register and set it to `Empty`, if it is allocated
|
||||||
pub(crate) fn drop_reg(&mut self, reg_id: RegId) -> Result<(), CompileError> {
|
pub(crate) fn drop_reg(&mut self, reg_id: RegId) -> Result<(), CompileError> {
|
||||||
if self.is_allocated(reg_id) {
|
if self.is_allocated(reg_id) {
|
||||||
self.push(Instruction::Drop { src: reg_id }.into_spanned(Span::unknown()))?;
|
// try using the block Span if available, since that's slightly more helpful than Span::unknown
|
||||||
|
let span = self.block_span.unwrap_or(Span::unknown());
|
||||||
|
self.push(Instruction::Drop { src: reg_id }.into_spanned(span))?;
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ pub fn eval_call<D: DebugContext>(
|
|||||||
call: &Call,
|
call: &Call,
|
||||||
input: PipelineData,
|
input: PipelineData,
|
||||||
) -> Result<PipelineData, ShellError> {
|
) -> Result<PipelineData, ShellError> {
|
||||||
engine_state.signals().check(call.head)?;
|
engine_state.signals().check(&call.head)?;
|
||||||
let decl = engine_state.get_decl(call.decl_id);
|
let decl = engine_state.get_decl(call.decl_id);
|
||||||
|
|
||||||
if !decl.is_known_external() && call.named_iter().any(|(flag, _, _)| flag.item == "help") {
|
if !decl.is_known_external() && call.named_iter().any(|(flag, _, _)| flag.item == "help") {
|
||||||
|
@ -292,6 +292,9 @@ fn eval_instruction<D: DebugContext>(
|
|||||||
) -> Result<InstructionResult, ShellError> {
|
) -> Result<InstructionResult, ShellError> {
|
||||||
use self::InstructionResult::*;
|
use self::InstructionResult::*;
|
||||||
|
|
||||||
|
// Check for interrupt if necessary
|
||||||
|
instruction.check_interrupt(ctx.engine_state, span)?;
|
||||||
|
|
||||||
// See the docs for `Instruction` for more information on what these instructions are supposed
|
// See the docs for `Instruction` for more information on what these instructions are supposed
|
||||||
// to do.
|
// to do.
|
||||||
match instruction {
|
match instruction {
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
BlockId, DeclId, Filesize, RegId, Span, Value, VarId,
|
BlockId, DeclId, Filesize, RegId, ShellError, Span, Value, VarId,
|
||||||
ast::{CellPath, Expression, Operator, Pattern, RangeInclusion},
|
ast::{CellPath, Expression, Operator, Pattern, RangeInclusion},
|
||||||
engine::EngineState,
|
engine::EngineState,
|
||||||
};
|
};
|
||||||
@ -382,6 +382,20 @@ impl Instruction {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check for an interrupt before certain instructions
|
||||||
|
pub fn check_interrupt(
|
||||||
|
&self,
|
||||||
|
engine_state: &EngineState,
|
||||||
|
span: &Span,
|
||||||
|
) -> Result<(), ShellError> {
|
||||||
|
match self {
|
||||||
|
Instruction::Jump { .. } | Instruction::Return { .. } => {
|
||||||
|
engine_state.signals().check(span)
|
||||||
|
}
|
||||||
|
_ => Ok(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is to document/enforce the size of `Instruction` in bytes.
|
// This is to document/enforce the size of `Instruction` in bytes.
|
||||||
|
@ -814,7 +814,7 @@ impl Reader {
|
|||||||
|
|
||||||
impl Read for Reader {
|
impl Read for Reader {
|
||||||
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
self.signals.check(self.span).map_err(ShellErrorBridge)?;
|
self.signals.check(&self.span).map_err(ShellErrorBridge)?;
|
||||||
self.reader.read(buf)
|
self.reader.read(buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1295,7 +1295,7 @@ fn generic_copy(
|
|||||||
let buf = &mut [0; DEFAULT_BUF_SIZE];
|
let buf = &mut [0; DEFAULT_BUF_SIZE];
|
||||||
let mut len = 0;
|
let mut len = 0;
|
||||||
loop {
|
loop {
|
||||||
signals.check(span)?;
|
signals.check(&span)?;
|
||||||
let n = match reader.read(buf) {
|
let n = match reader.read(buf) {
|
||||||
Ok(0) => break,
|
Ok(0) => break,
|
||||||
Ok(n) => n,
|
Ok(n) => n,
|
||||||
|
@ -784,7 +784,7 @@ where
|
|||||||
let span = span.unwrap_or(Span::unknown());
|
let span = span.unwrap_or(Span::unknown());
|
||||||
const OUTPUT_CHUNK_SIZE: usize = 8192;
|
const OUTPUT_CHUNK_SIZE: usize = 8192;
|
||||||
for chunk in data.as_ref().chunks(OUTPUT_CHUNK_SIZE) {
|
for chunk in data.as_ref().chunks(OUTPUT_CHUNK_SIZE) {
|
||||||
signals.check(span)?;
|
signals.check(&span)?;
|
||||||
destination
|
destination
|
||||||
.write_all(chunk)
|
.write_all(chunk)
|
||||||
.map_err(|err| io_error_map(err, location!()))?;
|
.map_err(|err| io_error_map(err, location!()))?;
|
||||||
|
@ -44,11 +44,11 @@ impl Signals {
|
|||||||
///
|
///
|
||||||
/// Otherwise, returns `Ok`.
|
/// Otherwise, returns `Ok`.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn check(&self, span: Span) -> Result<(), ShellError> {
|
pub fn check(&self, span: &Span) -> Result<(), ShellError> {
|
||||||
#[inline]
|
#[inline]
|
||||||
#[cold]
|
#[cold]
|
||||||
fn interrupt_error(span: Span) -> Result<(), ShellError> {
|
fn interrupt_error(span: &Span) -> Result<(), ShellError> {
|
||||||
Err(ShellError::Interrupted { span })
|
Err(ShellError::Interrupted { span: *span })
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.interrupted() {
|
if self.interrupted() {
|
||||||
|
@ -153,7 +153,7 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
|
|||||||
table.set_indent(cfg.opts.config.table.padding);
|
table.set_indent(cfg.opts.config.table.padding);
|
||||||
|
|
||||||
for (row, item) in input.iter().enumerate() {
|
for (row, item) in input.iter().enumerate() {
|
||||||
cfg.opts.signals.check(cfg.opts.span)?;
|
cfg.opts.signals.check(&cfg.opts.span)?;
|
||||||
check_value(item)?;
|
check_value(item)?;
|
||||||
|
|
||||||
let inner_cfg = cfg_expand_reset_table(cfg.clone(), available_width);
|
let inner_cfg = cfg_expand_reset_table(cfg.clone(), available_width);
|
||||||
@ -177,7 +177,7 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
|
|||||||
let mut index_column_width = 0;
|
let mut index_column_width = 0;
|
||||||
|
|
||||||
for (row, item) in input.iter().enumerate() {
|
for (row, item) in input.iter().enumerate() {
|
||||||
cfg.opts.signals.check(cfg.opts.span)?;
|
cfg.opts.signals.check(&cfg.opts.span)?;
|
||||||
check_value(item)?;
|
check_value(item)?;
|
||||||
|
|
||||||
let index = row + row_offset;
|
let index = row + row_offset;
|
||||||
@ -202,7 +202,7 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
|
|||||||
available_width -= index_column_width + extra_width + pad_width;
|
available_width -= index_column_width + extra_width + pad_width;
|
||||||
|
|
||||||
for (row, item) in input.iter().enumerate() {
|
for (row, item) in input.iter().enumerate() {
|
||||||
cfg.opts.signals.check(cfg.opts.span)?;
|
cfg.opts.signals.check(&cfg.opts.span)?;
|
||||||
check_value(item)?;
|
check_value(item)?;
|
||||||
|
|
||||||
let inner_cfg = cfg_expand_reset_table(cfg.clone(), available_width);
|
let inner_cfg = cfg_expand_reset_table(cfg.clone(), available_width);
|
||||||
@ -233,7 +233,7 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
|
|||||||
let mut index_column_width = 1;
|
let mut index_column_width = 1;
|
||||||
|
|
||||||
for (row, item) in input.iter().enumerate() {
|
for (row, item) in input.iter().enumerate() {
|
||||||
cfg.opts.signals.check(cfg.opts.span)?;
|
cfg.opts.signals.check(&cfg.opts.span)?;
|
||||||
check_value(item)?;
|
check_value(item)?;
|
||||||
|
|
||||||
let index = row + row_offset;
|
let index = row + row_offset;
|
||||||
@ -292,7 +292,7 @@ fn expand_list(input: &[Value], cfg: Cfg<'_>) -> TableResult {
|
|||||||
let mut column_width = 0;
|
let mut column_width = 0;
|
||||||
|
|
||||||
for (row, item) in input.iter().enumerate() {
|
for (row, item) in input.iter().enumerate() {
|
||||||
cfg.opts.signals.check(cfg.opts.span)?;
|
cfg.opts.signals.check(&cfg.opts.span)?;
|
||||||
check_value(item)?;
|
check_value(item)?;
|
||||||
|
|
||||||
let inner_cfg = cfg_expand_reset_table(cfg.clone(), available);
|
let inner_cfg = cfg_expand_reset_table(cfg.clone(), available);
|
||||||
@ -410,7 +410,7 @@ fn expanded_table_kv(record: &Record, cfg: Cfg<'_>) -> CellResult {
|
|||||||
table.set_indent(cfg.opts.config.table.padding);
|
table.set_indent(cfg.opts.config.table.padding);
|
||||||
|
|
||||||
for (i, (key, value)) in record.iter().enumerate() {
|
for (i, (key, value)) in record.iter().enumerate() {
|
||||||
cfg.opts.signals.check(cfg.opts.span)?;
|
cfg.opts.signals.check(&cfg.opts.span)?;
|
||||||
|
|
||||||
let cell = match expand_value(value, value_width, &cfg)? {
|
let cell = match expand_value(value, value_width, &cfg)? {
|
||||||
Some(val) => val,
|
Some(val) => val,
|
||||||
|
@ -50,7 +50,7 @@ fn kv_table(record: Record, opts: TableOpts<'_>) -> StringResult {
|
|||||||
table.set_indent(opts.config.table.padding);
|
table.set_indent(opts.config.table.padding);
|
||||||
|
|
||||||
for (i, (key, value)) in record.into_iter().enumerate() {
|
for (i, (key, value)) in record.into_iter().enumerate() {
|
||||||
opts.signals.check(opts.span)?;
|
opts.signals.check(&opts.span)?;
|
||||||
|
|
||||||
let value = nu_value_to_string_colored(&value, opts.config, &opts.style_computer);
|
let value = nu_value_to_string_colored(&value, opts.config, &opts.style_computer);
|
||||||
|
|
||||||
@ -100,7 +100,7 @@ fn create_table_with_header(
|
|||||||
table.set_indent(opts.config.table.padding);
|
table.set_indent(opts.config.table.padding);
|
||||||
|
|
||||||
for (row, item) in input.into_iter().enumerate() {
|
for (row, item) in input.into_iter().enumerate() {
|
||||||
opts.signals.check(opts.span)?;
|
opts.signals.check(&opts.span)?;
|
||||||
check_value(&item)?;
|
check_value(&item)?;
|
||||||
|
|
||||||
for (col, header) in headers.iter().enumerate() {
|
for (col, header) in headers.iter().enumerate() {
|
||||||
@ -137,7 +137,7 @@ fn create_table_with_header_and_index(
|
|||||||
table.set_row(0, head.clone());
|
table.set_row(0, head.clone());
|
||||||
|
|
||||||
for (row, item) in input.into_iter().enumerate() {
|
for (row, item) in input.into_iter().enumerate() {
|
||||||
opts.signals.check(opts.span)?;
|
opts.signals.check(&opts.span)?;
|
||||||
check_value(&item)?;
|
check_value(&item)?;
|
||||||
|
|
||||||
let text = get_table_row_index(&item, opts.config, row, row_offset);
|
let text = get_table_row_index(&item, opts.config, row, row_offset);
|
||||||
@ -164,7 +164,7 @@ fn create_table_with_no_header(
|
|||||||
table.set_indent(opts.config.table.padding);
|
table.set_indent(opts.config.table.padding);
|
||||||
|
|
||||||
for (row, item) in input.into_iter().enumerate() {
|
for (row, item) in input.into_iter().enumerate() {
|
||||||
opts.signals.check(opts.span)?;
|
opts.signals.check(&opts.span)?;
|
||||||
check_value(&item)?;
|
check_value(&item)?;
|
||||||
|
|
||||||
let (text, style) = get_string_value(&item, opts);
|
let (text, style) = get_string_value(&item, opts);
|
||||||
@ -186,7 +186,7 @@ fn create_table_with_no_header_and_index(
|
|||||||
table.set_indent(opts.config.table.padding);
|
table.set_indent(opts.config.table.padding);
|
||||||
|
|
||||||
for (row, item) in input.into_iter().enumerate() {
|
for (row, item) in input.into_iter().enumerate() {
|
||||||
opts.signals.check(opts.span)?;
|
opts.signals.check(&opts.span)?;
|
||||||
check_value(&item)?;
|
check_value(&item)?;
|
||||||
|
|
||||||
let index = get_table_row_index(&item, opts.config, row, row_offset);
|
let index = get_table_row_index(&item, opts.config, row, row_offset);
|
||||||
|
Reference in New Issue
Block a user