BLE_PIPESTATUS doesn't appear to update until after PROMPT_COMMAND is called
Closed this issue · 5 comments
ble version: 0.4.0-devel4+063249b
Bash version: 5.2.32(1)-release (aarch64-apple-darwin23.4.0)
$ ble/widget/display-shell-version
GNU bash, version 5.2.32(1)-release (aarch64-apple-darwin23.4.0)
ble.sh, version 0.4.0-devel4+063249b (noarch) [git 2.46.0, GNU Make 3.81, GNU Awk 5.3.0, API 4.0, (GNU MPFR 4.2.1, GNU MP 6.3.0)]
locale: LANG=en_US.UTF-8
terminal: TERM=xterm-256color wcwidth=15.0-west/15.1-2+ri, wezterm:20220408 (1;277;0)
options: +inherit_errexit
I would like to use a prompt that shows PIPESTATUS. I see that ble.sh provides it's own version of PIPESTATUS called BLE_PIPESTATUS - no problem! I don't mind using that over PIPESTATUS. However, BLE_PIPESTATUS does not appear to be properly updated before PROMPT_COMMAND is called, which makes it difficult to use in a prompt and appears to be different behavior than Bash't built-in PIPESTATUS. Here's a demo of the problem:
Bash default example
.bashrc contents
#!/usr/bin/env bash
# contents of minimal ~/.bashrc
function test_pipestatus() {
echo "PIPESTATUS: ${PIPESTATUS[@]}"
}
PROMPT_COMMAND="test_pipestatus"
behavior
PIPESTATUS: 0
bash-5.2$ true | false | true
PIPESTATUS: 0 1 0
bash-5.2$ true | false
PIPESTATUS: 0 1
bash-5.2$
Notice that the PIPESTATUS
array is filled and reports its contents on every call to test_pipestatus.
Now the ble.sh example
.bashrc contents
#!/usr/bin/env bash
# contents of minimal ~/.bashrc
[[ $- == *i* ]] && source "$HOME/.local/share/blesh/ble.sh" --noattach
function test_pipestatus() {
echo "BLE_PIPESTATUS: ${BLE_PIPESTATUS[@]}"
}
PROMPT_COMMAND="test_pipestatus"
[[ ${BLE_VERSION-} ]] && ble-attach
ble.sh behavior
BLE_PIPESTATUS:
bash-5.2$ true | false | true
BLE_PIPESTATUS:
bash-5.2$ true | false
[ble: exit 1]
BLE_PIPESTATUS: 0 1 0
bash-5.2$
Notice the BLE_PIPESTATUS
lags one command behind in its exit code reporting.
ble.sh example with restored PIPESTATUS
For completeness, we can also look at the behavior with exec_restore_pipestatus=1
. It looks like this does not actually properly restore PIPESTATUS to the built-in behavior:
.bashrc contents
#!/usr/bin/env bash
# contents of minimal ~/.bashrc
[[ $- == *i* ]] && source "$HOME/.local/share/blesh/ble.sh" --noattach
function test_pipestatus() {
echo "PIPESTATUS: ${PIPESTATUS[@]}, BLE_PIPESTATUS: ${BLE_PIPESTATUS[@]}"
}
PROMPT_COMMAND="test_pipestatus"
bleopt exec_restore_pipestatus=1 # restores PIPESTATUS
[[ ${BLE_VERSION-} ]] && ble-attach
ble.sh behavior with restored PIPESTATUS
PIPESTATUS: 0, BLE_PIPESTATUS:
bash-5.2$ true | false | true
PIPESTATUS: 0, BLE_PIPESTATUS:
bash-5.2$ true | false
[ble: exit 1]
PIPESTATUS: 1, BLE_PIPESTATUS: 0 1 0
bash-5.2$ true | false | true | true
PIPESTATUS: 0, BLE_PIPESTATUS: 0 1
bash-5.2$
Notice in this example, PIPESTATUS is restored, but never has more than one element.
I have really appreciated all the help and support Koichi. I have been really loving this project. Let me know if I'm doing something wrong or if there's an easy fix.
BLE_PIPESTATUS
is intended to be only set for the user command, i.e., the command that is input and run in the command line. PROMPT_COMMAND
is not the target of BLE_PIPESTATUS
, but I can expose it also for PROMPT_COMMAND
.
I'm open to whatever makes the most sense here. I know PIPESTATUS is essentially a magic variable and Bash makes it difficult to do things with it, so if BLE_PIPESTATUS or some other method is preferable, I'm open to whatever you think is best.
I was surprised in that last example that using bleopt exec_restore_pipestatus=1
didn't really restore PIPESTATUS to it's pre-blesh behavior. Is that even possible to do?
While looking at the code, I noticed that my thought when I implemented BLE_PIPESTATUS
was that BLE_PIPESTATUS
should be available in blehook PRECMD
but not in PROMPT_COMMAND
(blehook PRECMD
is ble's way of PROMPT_COMMAND
) because BLE_PIPESTATUS
is the ble-specific feature and the code using BLE_PIPESTATUS
should go into PRECMD
instead of PROMPT_COMMAND
. But anyway I can provide BLE_PIPESTATUS
also to PROMPT_COMMAND
.
I was surprised in that last example that using
bleopt exec_restore_pipestatus=1
didn't really restore PIPESTATUS to it's pre-blesh behavior.
The target of bleopt exec_restore_pipestatus=1
is also only user commands. Currently, PIPESTATUS
is not restored for the commands in PROMPT_COMMAND
even if you set bleopt exec_restore_pipestatus=1
.
ble.sh behavior with restored PIPESTATUS
PIPESTATUS: 0, BLE_PIPESTATUS: bash-5.2$ true | false | true PIPESTATUS: 0, BLE_PIPESTATUS: bash-5.2$ true | false [ble: exit 1] PIPESTATUS: 1, BLE_PIPESTATUS: 0 1 0 bash-5.2$ true | false | true | true PIPESTATUS: 0, BLE_PIPESTATUS: 0 1 bash-5.2$
So the above is the expected behavior of the current version. What bleopt exec_restore_pipestatus=1
provides is this:
$ bleopt exec_restore_pipestatus= # this is default
$ true | false | true
$ declare -p PIPESTATUS
declare -a PIPESTATUS=([0]="0")
$ bleopt exec_restore_pipestatus=1
$ true | false | true
$ declare -p PIPESTATUS
declare -a PIPESTATUS=([0]="0" [1]="1" [2]="0")
Is that even possible to do?
ble.sh uses a stupid way:
Lines 7392 to 7398 in 063249b
It inserts a dummy command (exit "${_saved_pipestus[0]}") | ... | (exit "${_saved_pipestus[n]}")
before the user command. This is the reason that I don't want to enable it by default.
I implemented them in commit 2788883.
WOW 🥇!
I can confirm, after running ble-update, this works as expected. Thank you so much!