Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 27 additions & 2 deletions crates/bashkit/src/interpreter/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
48 changes: 48 additions & 0 deletions crates/bashkit/tests/spec_cases/bash/variables.test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
8 changes: 4 additions & 4 deletions specs/009-implementation-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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}`, `\<newline>` 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}`, `\<newline>` 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 |
Expand Down
Loading