amber-lang / amber-lang/amber

[Feature] / [Question] / [RFC] Ability to access / propagate command stdout + stderr to the failed block

未關閉
#347 3 則留言 0 個 reaction 已指派 0 人 在 GitHub 檢視
enhancement
主要語言
Rust
星號
5.2k
分支
145
平均合併
5 天 3 小時
30 天內合併 PR
7

描述

## 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

貢獻指南

這個儲存庫沒有索引到貢獻指南

評估

這個 Issue 還沒有評估資料。

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。