From fbe9d6f52949511763230b3faeaca7bcf67bc2e2 Mon Sep 17 00:00:00 2001 From: WindSoilder Date: Thu, 1 Sep 2022 18:20:22 +0800 Subject: [PATCH] Highlight source value as well as failure point. (#6442) * show multiple errors at once for some commands * change from invalid item to source value --- crates/nu-command/src/filters/each.rs | 16 +++++----------- crates/nu-command/src/filters/mod.rs | 1 + crates/nu-command/src/filters/par_each.rs | 20 +++++++++++++++++--- crates/nu-command/src/filters/utils.rs | 11 +++++++++++ crates/nu-command/src/filters/where_.rs | 13 ++++++++++--- crates/nu-protocol/src/shell_error.rs | 2 +- 6 files changed, 45 insertions(+), 18 deletions(-) create mode 100644 crates/nu-command/src/filters/utils.rs diff --git a/crates/nu-command/src/filters/each.rs b/crates/nu-command/src/filters/each.rs index 3bf75dd039..923e31505f 100644 --- a/crates/nu-command/src/filters/each.rs +++ b/crates/nu-command/src/filters/each.rs @@ -1,9 +1,10 @@ +use super::utils::chain_error_with_input; use nu_engine::{eval_block, CallExt}; use nu_protocol::ast::Call; use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack}; use nu_protocol::{ - Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, ShellError, - Signature, Span, SyntaxShape, Value, + Category, Example, IntoInterruptiblePipelineData, IntoPipelineData, PipelineData, Signature, + Span, SyntaxShape, Value, }; #[derive(Clone)] @@ -172,7 +173,7 @@ impl Command for Each { ) { Ok(v) => v.into_value(span), Err(error) => { - let error = each_cmd_error(error, input_span); + let error = chain_error_with_input(error, input_span); Value::Error { error } } } @@ -227,7 +228,7 @@ impl Command for Each { ) { Ok(v) => v.into_value(span), Err(error) => { - let error = each_cmd_error(error, input_span); + let error = chain_error_with_input(error, input_span); Value::Error { error } } } @@ -260,13 +261,6 @@ impl Command for Each { } } -fn each_cmd_error(error_source: ShellError, input_span: Result) -> ShellError { - if let Ok(span) = input_span { - return ShellError::EvalBlockWithInput(span, vec![error_source]); - } - error_source -} - #[cfg(test)] mod test { use super::*; diff --git a/crates/nu-command/src/filters/mod.rs b/crates/nu-command/src/filters/mod.rs index 8ce7788a13..4d8fcba093 100644 --- a/crates/nu-command/src/filters/mod.rs +++ b/crates/nu-command/src/filters/mod.rs @@ -44,6 +44,7 @@ mod uniq; mod update; mod update_cells; mod upsert; +mod utils; mod where_; mod window; mod wrap; diff --git a/crates/nu-command/src/filters/par_each.rs b/crates/nu-command/src/filters/par_each.rs index b822c5af15..6fb1d1cf6d 100644 --- a/crates/nu-command/src/filters/par_each.rs +++ b/crates/nu-command/src/filters/par_each.rs @@ -7,6 +7,8 @@ use nu_protocol::{ }; use rayon::prelude::*; +use super::utils::chain_error_with_input; + #[derive(Clone)] pub struct ParEach; @@ -103,6 +105,7 @@ impl Command for ParEach { } } + let val_span = x.span(); match eval_block( &engine_state, &mut stack, @@ -112,7 +115,10 @@ impl Command for ParEach { redirect_stderr, ) { Ok(v) => v, - Err(error) => Value::Error { error }.into_pipeline_data(), + Err(error) => Value::Error { + error: chain_error_with_input(error, val_span), + } + .into_pipeline_data(), } }) .collect::>() @@ -151,6 +157,7 @@ impl Command for ParEach { } } + let val_span = x.span(); match eval_block( &engine_state, &mut stack, @@ -160,7 +167,10 @@ impl Command for ParEach { redirect_stderr, ) { Ok(v) => v, - Err(error) => Value::Error { error }.into_pipeline_data(), + Err(error) => Value::Error { + error: chain_error_with_input(error, val_span), + } + .into_pipeline_data(), } }) .collect::>() @@ -198,6 +208,7 @@ impl Command for ParEach { } } + let val_span = x.span(); match eval_block( &engine_state, &mut stack, @@ -207,7 +218,10 @@ impl Command for ParEach { redirect_stderr, ) { Ok(v) => v, - Err(error) => Value::Error { error }.into_pipeline_data(), + Err(error) => Value::Error { + error: chain_error_with_input(error, val_span), + } + .into_pipeline_data(), } }) .collect::>() diff --git a/crates/nu-command/src/filters/utils.rs b/crates/nu-command/src/filters/utils.rs new file mode 100644 index 0000000000..9729b5035a --- /dev/null +++ b/crates/nu-command/src/filters/utils.rs @@ -0,0 +1,11 @@ +use nu_protocol::{ShellError, Span}; + +pub fn chain_error_with_input( + error_source: ShellError, + input_span: Result, +) -> ShellError { + if let Ok(span) = input_span { + return ShellError::EvalBlockWithInput(span, vec![error_source]); + } + error_source +} diff --git a/crates/nu-command/src/filters/where_.rs b/crates/nu-command/src/filters/where_.rs index 28b55c7bf9..bd628ac6e3 100644 --- a/crates/nu-command/src/filters/where_.rs +++ b/crates/nu-command/src/filters/where_.rs @@ -1,3 +1,4 @@ +use super::utils::chain_error_with_input; use nu_engine::{eval_block, CallExt}; use nu_protocol::ast::Call; use nu_protocol::engine::{CaptureBlock, Command, EngineState, Stack}; @@ -83,7 +84,9 @@ impl Command for Where { None } } - Err(error) => Some(Value::Error { error }), + Err(error) => Some(Value::Error { + error: chain_error_with_input(error, x.span()), + }), } }) .into_pipeline_data(ctrlc)), @@ -124,7 +127,9 @@ impl Command for Where { None } } - Err(error) => Some(Value::Error { error }), + Err(error) => Some(Value::Error { + error: chain_error_with_input(error, x.span()), + }), } }) .into_pipeline_data(ctrlc)), @@ -149,7 +154,9 @@ impl Command for Where { None } } - Err(error) => Some(Value::Error { error }), + Err(error) => Some(Value::Error { + error: chain_error_with_input(error, x.span()), + }), } .into_pipeline_data(ctrlc)) } diff --git a/crates/nu-protocol/src/shell_error.rs b/crates/nu-protocol/src/shell_error.rs index 8fb90e8c59..1ad1d0a9fb 100644 --- a/crates/nu-protocol/src/shell_error.rs +++ b/crates/nu-protocol/src/shell_error.rs @@ -785,7 +785,7 @@ Either make sure {0} is a string, or add a 'to_string' entry for it in ENV_CONVE /// Failed to eval block with specific pipeline input. #[error("Eval block failed with pipeline input")] #[diagnostic(code(nu::shell::eval_block_with_input), url(docsrs))] - EvalBlockWithInput(#[label("Invalid item")] Span, #[related] Vec), + EvalBlockWithInput(#[label("source value")] Span, #[related] Vec), } impl From for ShellError {