use std::ffi::c_int;
use std::fmt::Write;
use yash_env::trap::Signal;
use yash_env::Env;
#[must_use]
pub fn print(signals: &[Signal], verbose: bool) -> String {
let mut specified = signals.iter().copied();
let mut all = Signal::iterator();
let iter: &mut dyn Iterator<Item = Signal> = if signals.is_empty() {
&mut all
} else {
&mut specified
};
let mut result = String::new();
for signal in iter {
let name = signal.as_str();
let name = name.strip_prefix("SIG").unwrap_or(name);
if verbose {
let number = signal as c_int;
writeln!(result, "{number}\t{name}").unwrap();
} else {
writeln!(result, "{name}").unwrap();
}
}
result
}
pub async fn execute(env: &mut Env, signals: &[Signal], verbose: bool) -> crate::Result {
let result = print(signals, verbose);
crate::common::output(env, &result).await
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn print_non_empty_non_verbose() {
let result = print(&[Signal::SIGTERM, Signal::SIGINT], false);
assert_eq!(result, "TERM\nINT\n");
let result = print(&[Signal::SIGKILL, Signal::SIGTSTP, Signal::SIGQUIT], false);
assert_eq!(result, "KILL\nTSTP\nQUIT\n");
}
#[test]
fn print_non_empty_verbose() {
let result = print(&[Signal::SIGTERM, Signal::SIGINT], true);
assert_eq!(result, "15\tTERM\n2\tINT\n");
let result = print(&[Signal::SIGKILL, Signal::SIGALRM, Signal::SIGQUIT], true);
assert_eq!(result, "9\tKILL\n14\tALRM\n3\tQUIT\n");
}
#[test]
fn print_all_non_verbose() {
let result = print(&[], false);
assert!(result.contains("HUP\n"), "result: {result:?}");
assert!(result.contains("INT\n"), "result: {result:?}");
assert!(result.contains("KILL\n"), "result: {result:?}");
assert!(result.contains("QUIT\n"), "result: {result:?}");
assert!(result.contains("STOP\n"), "result: {result:?}");
assert!(result.contains("TERM\n"), "result: {result:?}");
assert!(result.contains("TSTP\n"), "result: {result:?}");
assert!(result.contains("TTIN\n"), "result: {result:?}");
assert!(result.contains("TTOU\n"), "result: {result:?}");
}
}