mirror of
https://github.com/nushell/nushell.git
synced 2025-08-19 08:41:29 +02:00
Error on non-zero exit statuses (#13515)
# Description This PR makes it so that non-zero exit codes and termination by signal are treated as a normal `ShellError`. Currently, these are silent errors. That is, if an external command fails, then it's code block is aborted, but the parent block can sometimes continue execution. E.g., see #8569 and this example: ```nushell [1 2] | each { ^false } ``` Before this would give: ``` ╭───┬──╮ │ 0 │ │ │ 1 │ │ ╰───┴──╯ ``` Now, this shows an error: ``` Error: nu:🐚:eval_block_with_input × Eval block failed with pipeline input ╭─[entry #1:1:2] 1 │ [1 2] | each { ^false } · ┬ · ╰── source value ╰──── Error: nu:🐚:non_zero_exit_code × External command had a non-zero exit code ╭─[entry #1:1:17] 1 │ [1 2] | each { ^false } · ──┬── · ╰── exited with code 1 ╰──── ``` This PR fixes #12874, fixes #5960, fixes #10856, and fixes #5347. This PR also partially addresses #10633 and #10624 (only the last command of a pipeline is currently checked). It looks like #8569 is already fixed, but this PR will make sure it is definitely fixed (fixes #8569). # User-Facing Changes - Non-zero exit codes and termination by signal now cause an error to be thrown. - The error record value passed to a `catch` block may now have an `exit_code` column containing the integer exit code if the error was due to an external command. - Adds new config values, `display_errors.exit_code` and `display_errors.termination_signal`, which determine whether an error message should be printed in the respective error cases. For non-interactive sessions, these are set to `true`, and for interactive sessions `display_errors.exit_code` is false (via the default config). # Tests Added a few tests. # After Submitting - Update docs and book. - Future work: - Error if other external commands besides the last in a pipeline exit with a non-zero exit code. Then, deprecate `do -c` since this will be the default behavior everywhere. - Add a better mechanism for exit codes and deprecate `$env.LAST_EXIT_CODE` (it's buggy).
This commit is contained in:
29
crates/nu-protocol/src/config/display_errors.rs
Normal file
29
crates/nu-protocol/src/config/display_errors.rs
Normal file
@@ -0,0 +1,29 @@
|
||||
use super::prelude::*;
|
||||
use crate as nu_protocol;
|
||||
use crate::ShellError;
|
||||
|
||||
#[derive(Clone, Copy, Debug, IntoValue, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct DisplayErrors {
|
||||
pub exit_code: bool,
|
||||
pub termination_signal: bool,
|
||||
}
|
||||
|
||||
impl DisplayErrors {
|
||||
pub fn should_show(&self, error: &ShellError) -> bool {
|
||||
match error {
|
||||
ShellError::NonZeroExitCode { .. } => self.exit_code,
|
||||
#[cfg(unix)]
|
||||
ShellError::TerminatedBySignal { .. } => self.termination_signal,
|
||||
_ => true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for DisplayErrors {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
exit_code: true,
|
||||
termination_signal: true,
|
||||
}
|
||||
}
|
||||
}
|
@@ -12,6 +12,7 @@ pub use self::completer::{
|
||||
CompleterConfig, CompletionAlgorithm, CompletionSort, ExternalCompleterConfig,
|
||||
};
|
||||
pub use self::datetime_format::DatetimeFormatConfig;
|
||||
pub use self::display_errors::DisplayErrors;
|
||||
pub use self::filesize::FilesizeConfig;
|
||||
pub use self::helper::extract_value;
|
||||
pub use self::history::{HistoryConfig, HistoryFileFormat};
|
||||
@@ -28,6 +29,7 @@ pub use self::table::{FooterMode, TableConfig, TableIndexMode, TableMode, TrimSt
|
||||
|
||||
mod completer;
|
||||
mod datetime_format;
|
||||
mod display_errors;
|
||||
mod filesize;
|
||||
mod helper;
|
||||
mod history;
|
||||
@@ -67,6 +69,7 @@ pub struct Config {
|
||||
pub cursor_shape: CursorShapeConfig,
|
||||
pub datetime_format: DatetimeFormatConfig,
|
||||
pub error_style: ErrorStyle,
|
||||
pub display_errors: DisplayErrors,
|
||||
pub use_kitty_protocol: bool,
|
||||
pub highlight_resolved_externals: bool,
|
||||
/// Configuration for plugins.
|
||||
@@ -121,6 +124,7 @@ impl Default for Config {
|
||||
keybindings: Vec::new(),
|
||||
|
||||
error_style: ErrorStyle::Fancy,
|
||||
display_errors: DisplayErrors::default(),
|
||||
|
||||
use_kitty_protocol: false,
|
||||
highlight_resolved_externals: false,
|
||||
@@ -609,6 +613,29 @@ impl Value {
|
||||
"show_banner" => {
|
||||
process_bool_config(value, &mut errors, &mut config.show_banner);
|
||||
}
|
||||
"display_errors" => {
|
||||
if let Value::Record { val, .. } = value {
|
||||
val.to_mut().retain_mut(|key2, value| {
|
||||
let span = value.span();
|
||||
match key2 {
|
||||
"exit_code" => {
|
||||
process_bool_config(value, &mut errors, &mut config.display_errors.exit_code);
|
||||
}
|
||||
"termination_signal" => {
|
||||
process_bool_config(value, &mut errors, &mut config.display_errors.termination_signal);
|
||||
}
|
||||
_ => {
|
||||
report_invalid_key(&[key, key2], span, &mut errors);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
true
|
||||
});
|
||||
} else {
|
||||
report_invalid_value("should be a record", span, &mut errors);
|
||||
*value = config.display_errors.into_value(span);
|
||||
}
|
||||
}
|
||||
"render_right_prompt_on_last_line" => {
|
||||
process_bool_config(value, &mut errors, &mut config.render_right_prompt_on_last_line);
|
||||
}
|
||||
|
Reference in New Issue
Block a user