[Feature] / [Question] / [RFC] Ability to access / propagate command stdout + stderr to the failed block
- Dominant language
- Rust
- Stars
- 5.2k
- Forks
- 145
- Avg merge
- 5d 3h
- Merged PRs (30d)
- 7
Description
## Description
It appears that today, there is no way to access stdout + stderr of a command which failed (exited with non zero status code) inside the `failed` block or outside of it as part of the command return value.
I tried multiple approaches without success - please correct me if I'm wrong and I missed something.
## Background, Context, Use Case
Today Amber already offers some improved error / failure handling of commands which exited with non-zero status code, but since I don't have access to command stdout + stderr, I can't improve and add additional user-friendly error handling in the `failed` block (or outside of it)
In ideal world, each program would exit with a different non-zero status code for each error scenario, but that's not a case with majority of the programs today. In a lot of cases only way to determine error type is to parse and inspect the command string output (stdout / stderr).
I know that one workaround I could perhaps use is to redirect command stderr output to stdout, but this is not ideal and still only works in case command exited with zero status code.
Let's take this code for example:
```amber
import * from "std"
main (args) {
echo ""
echo "scenario 1 - exit code 0 with failed block"
echo ""
let output = silent $ echo "stdout" ; >&2 echo "stderr" ; exit 0 $ failed {
echo "Should not get here"
}
echo ""
echo "output"
echo "{output}"
echo "status: {status}"
echo "end"
echo ""
echo "scenario 2 - exit code 2"
echo ""
let output = silent $ echo "stdout" ; >&2 echo "stderr" ; exit 2 $ failed {
echo "Inside failed block"
echo "status: {status}"
}
echo ""
echo "output"
echo "{output}"
echo "status: {status}"
echo "end"
echo ""
echo "scenario 3 - exit code 2 with unsafe"
echo ""
let output = silent unsafe $ echo "stdout" ; >&2 echo "stderr" ; exit 2 $
echo ""
echo "output"
echo "{output}"
echo "status: {status}"
echo "end"
}
```
Output will look like this:
```
$ bash test.sh
scenario 1 - exit code 0 with failed block
stderr
output
stdout
stauts: 0
end
scenario 2 - exit code 2
stderr
Inside failed block
output
stdout
stauts: 2
end
scenario 3 - exit code 2 with unsafe
stderr
output
stdout
stauts: 2
end
```
## Proposed Change / Implementation
I haven't had much time yet to check the internals and think how this could look, but since `status` expression is already available in the `failed` block we could perhaps try to redirect and capture stdout + stderr of each command and then make it available via special variables or expression inside the block.
Perhaps something along the lines of (pseudo code):
```
import * from "std"
main (args) {
// Option 1 via special variables / expression which is available inside and
// outside the failed block
let output = silent $ echo "stdout" ; >&2 echo "stderr" ; exit 2 $ failed {
echo "Inside failed block"
echo "status: {status}"
echo "stdout: {stdout}"
echo "stderr: {stderr}"
if contains(stdout, "errNoPermission") {
echo "Command returned no permission error."
echo "This likely indicates your session key has expired. Please visit XXX for more information on how to retrieve new or refresh the session key."
}
}
// Option 2 via return values
let stderr, stdout = silent $ echo "stdout" ; >&2 echo "stderr" ; exit 2 $ failed {
echo "Inside failed block"
echo "status: {status}"
echo "stdout: {stdout}"
echo "stderr: {stderr}"
}
echo "status: {status}"
echo "stdout: {stdout}"
echo "stderr: {stderr}"
}
```
Thanks.
## Related PRs, Issues
- This issue looks somewhat related, note sure if we should merge or mark mine as duplicate - https://github.com/amber-lang/amber/issues/287
- https://github.com/amber-lang/amber/issues/296
## Links
- Docs - https://docs.amber-lang.com/basic_syntax/commands
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.