Skip to content

Commit 2d83847

Browse files
chaliyclaude
andauthored
feat(interpreter): implement trap -p flag and sorted trap listing (#258)
## Summary - Add `trap -p` flag to print traps in re-executable format - `trap -p SIG` prints trap for specific signal - Sort trap listing output alphabetically for deterministic ordering ## Changes - `crates/bashkit/src/interpreter/mod.rs`: Add `-p` flag handling in trap builtin, sort trap listings - `crates/bashkit/tests/spec_cases/bash/variables.test.sh`: 5 new spec tests - `specs/009-implementation-status.md`: Update test counts (variables 92→97, Bash 906→911, Total 1324→1329) ## Test plan - [x] `cargo test --all-features` passes (including bash comparison tests) - [x] `cargo fmt --check` clean - [x] `cargo clippy --all-targets --all-features -- -D warnings` clean Co-authored-by: Claude <noreply@anthropic.com>
1 parent e3d814c commit 2d83847

File tree

3 files changed

+79
-6
lines changed

3 files changed

+79
-6
lines changed

crates/bashkit/src/interpreter/mod.rs

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2843,15 +2843,40 @@ impl Interpreter {
28432843
// Handle `trap` - register signal/event handlers
28442844
if name == "trap" {
28452845
if args.is_empty() {
2846-
// List traps
2846+
// List all traps
28472847
let mut output = String::new();
2848-
for (sig, cmd) in &self.traps {
2848+
let mut sorted: Vec<_> = self.traps.iter().collect();
2849+
sorted.sort_by_key(|(sig, _)| (*sig).clone());
2850+
for (sig, cmd) in sorted {
28492851
output.push_str(&format!("trap -- '{}' {}\n", cmd, sig));
28502852
}
28512853
let mut result = ExecResult::ok(output);
28522854
result = self.apply_redirections(result, &command.redirects).await?;
28532855
return Ok(result);
28542856
}
2857+
// Handle -p flag (print traps)
2858+
if args[0] == "-p" {
2859+
let mut output = String::new();
2860+
if args.len() == 1 {
2861+
// trap -p: print all traps
2862+
let mut sorted: Vec<_> = self.traps.iter().collect();
2863+
sorted.sort_by_key(|(sig, _)| (*sig).clone());
2864+
for (sig, cmd) in sorted {
2865+
output.push_str(&format!("trap -- '{}' {}\n", cmd, sig));
2866+
}
2867+
} else {
2868+
// trap -p SIG ...: print specific traps
2869+
for sig in &args[1..] {
2870+
let sig_upper = sig.to_uppercase();
2871+
if let Some(cmd) = self.traps.get(&sig_upper) {
2872+
output.push_str(&format!("trap -- '{}' {}\n", cmd, sig_upper));
2873+
}
2874+
}
2875+
}
2876+
let mut result = ExecResult::ok(output);
2877+
result = self.apply_redirections(result, &command.redirects).await?;
2878+
return Ok(result);
2879+
}
28552880
if args.len() == 1 {
28562881
// trap '' or trap - : reset signal
28572882
let sig = args[0].to_uppercase();

crates/bashkit/tests/spec_cases/bash/variables.test.sh

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,3 +719,51 @@ echo "$state"
719719
### expect
720720
set -o xtrace
721721
### end
722+
723+
### trap_print_specific
724+
# trap -p shows specific trap
725+
trap "echo bye" EXIT
726+
trap -p EXIT
727+
trap - EXIT
728+
### expect
729+
trap -- 'echo bye' EXIT
730+
### end
731+
732+
### trap_print_all
733+
# trap -p with no args shows all traps
734+
trap "echo cleanup" EXIT
735+
trap "echo oops" ERR
736+
trap -p | sort
737+
trap - EXIT
738+
trap - ERR
739+
### expect
740+
trap -- 'echo cleanup' EXIT
741+
trap -- 'echo oops' ERR
742+
### end
743+
744+
### trap_print_unset
745+
# trap -p for unset signal produces no output
746+
result=$(trap -p INT)
747+
echo "result:${result}end"
748+
### expect
749+
result:end
750+
### end
751+
752+
### trap_list_all
753+
# trap with no args lists all traps
754+
trap "echo done" EXIT
755+
trap | sort
756+
trap - EXIT
757+
### expect
758+
trap -- 'echo done' EXIT
759+
### end
760+
761+
### trap_reset_and_print
762+
# trap - removes trap, trap -p confirms
763+
trap "echo bye" EXIT
764+
trap - EXIT
765+
result=$(trap -p EXIT)
766+
echo "after reset:${result}end"
767+
### expect
768+
after reset:end
769+
### end

specs/009-implementation-status.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,17 +103,17 @@ Bashkit implements IEEE 1003.1-2024 Shell Command Language. See
103103

104104
## Spec Test Coverage
105105

106-
**Total spec test cases:** 1324 (1319 pass, 5 skip)
106+
**Total spec test cases:** 1329 (1324 pass, 5 skip)
107107

108108
| Category | Cases | In CI | Pass | Skip | Notes |
109109
|----------|-------|-------|------|------|-------|
110-
| Bash (core) | 906 | Yes | 901 | 5 | `bash_spec_tests` in CI |
110+
| Bash (core) | 911 | Yes | 906 | 5 | `bash_spec_tests` in CI |
111111
| AWK | 96 | Yes | 96 | 0 | loops, arrays, -v, ternary, field assign, getline, %.6g |
112112
| Grep | 76 | Yes | 76 | 0 | -z, -r, -a, -b, -H, -h, -f, -P, --include, --exclude, binary detect |
113113
| Sed | 75 | Yes | 75 | 0 | hold space, change, regex ranges, -E |
114114
| JQ | 114 | Yes | 114 | 0 | reduce, walk, regex funcs, --arg/--argjson, combined flags, input/inputs, env |
115115
| Python | 57 | Yes | 57 | 0 | embedded Python (Monty) |
116-
| **Total** | **1324** | **Yes** | **1319** | **5** | |
116+
| **Total** | **1329** | **Yes** | **1324** | **5** | |
117117

118118
### Bash Spec Tests Breakdown
119119

@@ -157,7 +157,7 @@ Bashkit implements IEEE 1003.1-2024 Shell Command Language. See
157157
| test-operators.test.sh | 17 | file/string tests |
158158
| time.test.sh | 11 | Wall-clock only (user/sys always 0) |
159159
| timeout.test.sh | 17 | |
160-
| variables.test.sh | 92 | includes special vars, prefix env, PIPESTATUS, trap EXIT, `${var@Q}`, `\<newline>` line continuation, PWD/HOME/USER/HOSTNAME/BASH_VERSION/SECONDS, `set -x` xtrace, `shopt` builtin, nullglob, `set -o`/`set +o` display |
160+
| variables.test.sh | 97 | includes special vars, prefix env, PIPESTATUS, trap EXIT, `${var@Q}`, `\<newline>` line continuation, PWD/HOME/USER/HOSTNAME/BASH_VERSION/SECONDS, `set -x` xtrace, `shopt` builtin, nullglob, `set -o`/`set +o` display, `trap -p` |
161161
| wc.test.sh | 35 | word count (5 skipped) |
162162
| type.test.sh | 15 | `type`, `which`, `hash` builtins |
163163
| declare.test.sh | 23 | `declare`/`typeset`, `-i`, `-r`, `-x`, `-a`, `-p`, `-n` nameref, `-l`/`-u` case conversion |

0 commit comments

Comments
 (0)