diff --git a/crates/bashkit/src/interpreter/mod.rs b/crates/bashkit/src/interpreter/mod.rs index 77d04f92..6dd870fc 100644 --- a/crates/bashkit/src/interpreter/mod.rs +++ b/crates/bashkit/src/interpreter/mod.rs @@ -2843,15 +2843,40 @@ impl Interpreter { // Handle `trap` - register signal/event handlers if name == "trap" { if args.is_empty() { - // List traps + // List all traps let mut output = String::new(); - for (sig, cmd) in &self.traps { + let mut sorted: Vec<_> = self.traps.iter().collect(); + sorted.sort_by_key(|(sig, _)| (*sig).clone()); + for (sig, cmd) in sorted { output.push_str(&format!("trap -- '{}' {}\n", cmd, sig)); } let mut result = ExecResult::ok(output); result = self.apply_redirections(result, &command.redirects).await?; return Ok(result); } + // Handle -p flag (print traps) + if args[0] == "-p" { + let mut output = String::new(); + if args.len() == 1 { + // trap -p: print all traps + let mut sorted: Vec<_> = self.traps.iter().collect(); + sorted.sort_by_key(|(sig, _)| (*sig).clone()); + for (sig, cmd) in sorted { + output.push_str(&format!("trap -- '{}' {}\n", cmd, sig)); + } + } else { + // trap -p SIG ...: print specific traps + for sig in &args[1..] { + let sig_upper = sig.to_uppercase(); + if let Some(cmd) = self.traps.get(&sig_upper) { + output.push_str(&format!("trap -- '{}' {}\n", cmd, sig_upper)); + } + } + } + let mut result = ExecResult::ok(output); + result = self.apply_redirections(result, &command.redirects).await?; + return Ok(result); + } if args.len() == 1 { // trap '' or trap - : reset signal let sig = args[0].to_uppercase(); diff --git a/crates/bashkit/tests/spec_cases/bash/variables.test.sh b/crates/bashkit/tests/spec_cases/bash/variables.test.sh index b3df3fb8..3b083192 100644 --- a/crates/bashkit/tests/spec_cases/bash/variables.test.sh +++ b/crates/bashkit/tests/spec_cases/bash/variables.test.sh @@ -719,3 +719,51 @@ echo "$state" ### expect set -o xtrace ### end + +### trap_print_specific +# trap -p shows specific trap +trap "echo bye" EXIT +trap -p EXIT +trap - EXIT +### expect +trap -- 'echo bye' EXIT +### end + +### trap_print_all +# trap -p with no args shows all traps +trap "echo cleanup" EXIT +trap "echo oops" ERR +trap -p | sort +trap - EXIT +trap - ERR +### expect +trap -- 'echo cleanup' EXIT +trap -- 'echo oops' ERR +### end + +### trap_print_unset +# trap -p for unset signal produces no output +result=$(trap -p INT) +echo "result:${result}end" +### expect +result:end +### end + +### trap_list_all +# trap with no args lists all traps +trap "echo done" EXIT +trap | sort +trap - EXIT +### expect +trap -- 'echo done' EXIT +### end + +### trap_reset_and_print +# trap - removes trap, trap -p confirms +trap "echo bye" EXIT +trap - EXIT +result=$(trap -p EXIT) +echo "after reset:${result}end" +### expect +after reset:end +### end diff --git a/specs/009-implementation-status.md b/specs/009-implementation-status.md index abb10d45..2130b41a 100644 --- a/specs/009-implementation-status.md +++ b/specs/009-implementation-status.md @@ -103,17 +103,17 @@ Bashkit implements IEEE 1003.1-2024 Shell Command Language. See ## Spec Test Coverage -**Total spec test cases:** 1324 (1319 pass, 5 skip) +**Total spec test cases:** 1329 (1324 pass, 5 skip) | Category | Cases | In CI | Pass | Skip | Notes | |----------|-------|-------|------|------|-------| -| Bash (core) | 906 | Yes | 901 | 5 | `bash_spec_tests` in CI | +| Bash (core) | 911 | Yes | 906 | 5 | `bash_spec_tests` in CI | | AWK | 96 | Yes | 96 | 0 | loops, arrays, -v, ternary, field assign, getline, %.6g | | Grep | 76 | Yes | 76 | 0 | -z, -r, -a, -b, -H, -h, -f, -P, --include, --exclude, binary detect | | Sed | 75 | Yes | 75 | 0 | hold space, change, regex ranges, -E | | JQ | 114 | Yes | 114 | 0 | reduce, walk, regex funcs, --arg/--argjson, combined flags, input/inputs, env | | Python | 57 | Yes | 57 | 0 | embedded Python (Monty) | -| **Total** | **1324** | **Yes** | **1319** | **5** | | +| **Total** | **1329** | **Yes** | **1324** | **5** | | ### Bash Spec Tests Breakdown @@ -157,7 +157,7 @@ Bashkit implements IEEE 1003.1-2024 Shell Command Language. See | test-operators.test.sh | 17 | file/string tests | | time.test.sh | 11 | Wall-clock only (user/sys always 0) | | timeout.test.sh | 17 | | -| variables.test.sh | 92 | includes special vars, prefix env, PIPESTATUS, trap EXIT, `${var@Q}`, `\` line continuation, PWD/HOME/USER/HOSTNAME/BASH_VERSION/SECONDS, `set -x` xtrace, `shopt` builtin, nullglob, `set -o`/`set +o` display | +| variables.test.sh | 97 | includes special vars, prefix env, PIPESTATUS, trap EXIT, `${var@Q}`, `\` line continuation, PWD/HOME/USER/HOSTNAME/BASH_VERSION/SECONDS, `set -x` xtrace, `shopt` builtin, nullglob, `set -o`/`set +o` display, `trap -p` | | wc.test.sh | 35 | word count (5 skipped) | | type.test.sh | 15 | `type`, `which`, `hash` builtins | | declare.test.sh | 23 | `declare`/`typeset`, `-i`, `-r`, `-x`, `-a`, `-p`, `-n` nameref, `-l`/`-u` case conversion |