From 5e664250accdd94387b3dbbd7c426effe96568df Mon Sep 17 00:00:00 2001 From: Igor Date: Wed, 23 Oct 2024 13:46:50 +0400 Subject: [PATCH] ERR and DEBUG without numbers --- brush-core/src/builtins/kill.rs | 11 ++--- brush-core/src/builtins/trap.rs | 7 ++- brush-core/src/patterns.rs | 3 +- brush-core/src/traps.rs | 50 +++++++++++++--------- brush-shell/tests/cases/builtins/kill.yaml | 2 - 5 files changed, 42 insertions(+), 31 deletions(-) diff --git a/brush-core/src/builtins/kill.rs b/brush-core/src/builtins/kill.rs index ad4fa2df..e7ba2a26 100644 --- a/brush-core/src/builtins/kill.rs +++ b/brush-core/src/builtins/kill.rs @@ -1,7 +1,7 @@ use clap::Parser; use std::io::Write; -use crate::traps::{self, TrapSignal}; +use crate::traps::TrapSignal; use crate::{builtins, commands, error}; /// Signal a job or process. @@ -91,7 +91,9 @@ fn print_signals( PrintSignal::Name(s.as_str().strip_prefix("SIG").unwrap_or(s.as_str())) }) } else { - TrapSignal::try_from(s.as_str()).map(|s| PrintSignal::Num(i32::from(s))) + TrapSignal::try_from(s.as_str()).map(|sig| { + i32::try_from(sig).map_or(PrintSignal::Name(sig.as_str()), PrintSignal::Num) + }) }; match signal { @@ -108,10 +110,9 @@ fn print_signals( } } } else { - return traps::format_signals( + return crate::traps::format_signals( context.stdout(), - TrapSignal::iterator() - .filter(|s| !matches!(s, TrapSignal::Err | TrapSignal::Debug | TrapSignal::Exit)), + TrapSignal::iterator().filter(|s| matches!(s, TrapSignal::Signal(_))), ) .map(|()| builtins::ExitCode::Success); } diff --git a/brush-core/src/builtins/trap.rs b/brush-core/src/builtins/trap.rs index 33cff639..5a6eb603 100644 --- a/brush-core/src/builtins/trap.rs +++ b/brush-core/src/builtins/trap.rs @@ -24,8 +24,11 @@ impl builtins::Command for TrapCommand { mut context: commands::ExecutionContext<'_>, ) -> Result { if self.list_signals { - crate::traps::format_signals(context.stdout(), TrapSignal::iterator()) - .map(|()| builtins::ExitCode::Success) + crate::traps::format_signals( + context.stdout(), + TrapSignal::iterator().filter(|s| matches!(s, TrapSignal::Signal(_))), + ) + .map(|()| builtins::ExitCode::Success) } else if self.print_trap_commands || self.args.is_empty() { if !self.args.is_empty() { for signal_type in &self.args { diff --git a/brush-core/src/patterns.rs b/brush-core/src/patterns.rs index 728621c7..e0544b7b 100644 --- a/brush-core/src/patterns.rs +++ b/brush-core/src/patterns.rs @@ -285,7 +285,8 @@ impl Pattern { } if self.multiline { - // Set option for multiline matching + set option for allowing '.' pattern to match newline. + // Set option for multiline matching + set option for allowing '.' pattern to match + // newline. regex_str.push_str("(?ms)"); } diff --git a/brush-core/src/traps.rs b/brush-core/src/traps.rs index e0110a1a..25729f2c 100644 --- a/brush-core/src/traps.rs +++ b/brush-core/src/traps.rs @@ -63,8 +63,9 @@ pub fn format_signals( it: impl Iterator, ) -> Result<(), error::Error> { let it = it - .sorted_by(|a, b| Ord::cmp(&i32::from(*a), &i32::from(*b))) - .format_with("\n", |s, f| f(&format_args!("{}) {s}", i32::from(s)))); + .filter_map(|s| i32::try_from(s).ok().map(|n| (s, n))) + .sorted_by(|a, b| Ord::cmp(&a.1, &b.1)) + .format_with("\n", |s, f| f(&format_args!("{}) {}", s.1, s.0))); write!(f, "{it}")?; Ok(()) } @@ -85,9 +86,10 @@ impl FromStr for TrapSignal { impl TryFrom for TrapSignal { type Error = error::Error; fn try_from(value: i32) -> Result { + // NOTE: DEBUG and ERR are real-time signals, defined based on NSIG or SIGRTMAX (is not + // available on bsd-like systems), + // and don't have persistent numbers across platforms, so we skip them here. Ok(match value { - 32 => TrapSignal::Debug, - 33 => TrapSignal::Err, 0 => TrapSignal::Exit, #[cfg(unix)] value => TrapSignal::Signal( @@ -104,37 +106,43 @@ impl TryFrom for TrapSignal { impl TryFrom<&str> for TrapSignal { type Error = error::Error; fn try_from(value: &str) -> Result { + #[allow(unused_mut)] // on not unix platforms let mut s = value.to_ascii_uppercase(); - // Bash compatibility: - // support for signal names without the `SIG` prefix, for example `HUP` -> `SIGHUP` - if !s.starts_with("SIG") { - s.insert_str(0, "SIG"); - } Ok(match s.as_str() { - "SIGDEBUG" => TrapSignal::Debug, - "SIGERR" => TrapSignal::Err, - "SIGEXIT" => TrapSignal::Exit, + "DEBUG" => TrapSignal::Debug, + "ERR" => TrapSignal::Err, + "EXIT" => TrapSignal::Exit, #[cfg(unix)] - _ => nix::sys::signal::Signal::from_str(s.as_str()) - .map(TrapSignal::Signal) - .map_err(|_| error::Error::InvalidSignal(value.into()))?, + _ => { + // Bash compatibility: + // support for signal names without the `SIG` prefix, for example `HUP` -> `SIGHUP` + if !s.starts_with("SIG") { + s.insert_str(0, "SIG"); + } + nix::sys::signal::Signal::from_str(s.as_str()) + .map(TrapSignal::Signal) + .map_err(|_| error::Error::InvalidSignal(value.into()))? + } #[cfg(not(unix))] _ => return Err(error::Error::InvalidSignal(value.into())), }) } } -impl From for i32 { - fn from(value: TrapSignal) -> Self { - match value { +#[derive(Debug, Clone, Copy)] +pub struct DoesntHaveANumber; + +impl TryFrom for i32 { + type Error = DoesntHaveANumber; + fn try_from(value: TrapSignal) -> Result { + Ok(match value { #[cfg(unix)] TrapSignal::Signal(s) => s as i32, - TrapSignal::Debug => 32, - TrapSignal::Err => 33, TrapSignal::Exit => 0, - } + _ => return Err(DoesntHaveANumber), + }) } } diff --git a/brush-shell/tests/cases/builtins/kill.yaml b/brush-shell/tests/cases/builtins/kill.yaml index 2779f322..4c34afdd 100644 --- a/brush-shell/tests/cases/builtins/kill.yaml +++ b/brush-shell/tests/cases/builtins/kill.yaml @@ -43,6 +43,4 @@ cases: kill -l int kill -l SIGHUP kill -l EXIT - kill -l ERR - kill -l DEBUG