fix(bash): rework #1509 to recover from the preexec failure (#1729)

In GitHub #1509, we blocked the unintended preexec event caused by the
keybinding of Atuin.  However, with that fix, the preexec event for
the intended user command is still missing.  In this patch, we try to
manually run the preexec hook when we detected the unintended preexec
(which means the missing intended preexec).

References:

https://github.com/atuinsh/atuin/pull/1509
https://forum.atuin.sh/t/atuin-bash-and-ble-sh/175
https://github.com/atuinsh/atuin/issues/1003#issuecomment-1947905213
https://github.com/atuinsh/atuin/pull/1727
https://github.com/atuinsh/atuin/pull/1728
This commit is contained in:
Koichi Murase 2024-02-18 04:43:25 +09:00 committed by Ellie Huxtable
parent 1464cb657a
commit 386771da5c

View File

@ -17,12 +17,19 @@ export ATUIN_SESSION
ATUIN_HISTORY_ID="" ATUIN_HISTORY_ID=""
__atuin_preexec() { __atuin_preexec() {
# Workaround for old versions of bash-preexec
if [[ ! ${BLE_ATTACHED-} ]]; then if [[ ! ${BLE_ATTACHED-} ]]; then
# With bash-preexec, preexec may be called even for the command run by # In older versions of bash-preexec, the preexec hook may be called
# keybindings. There is no general and robust way to detect the # even for the commands run by keybindings. There is no general and
# command for keybindings, but at least we want to exclude Atuin's # robust way to detect the command for keybindings, but at least we
# keybindings. # want to exclude Atuin's keybindings. When the preexec hook is called
[[ $BASH_COMMAND == '__atuin_history'* && $BASH_COMMAND != "$1" ]] && return 0 # for a keybinding, the preexec hook for the user command will not
# fire, so we instead set a fake ATUIN_HISTORY_ID here to notify
# __atuin_precmd of this failure.
if [[ $BASH_COMMAND == '__atuin_history'* && $BASH_COMMAND != "$1" ]]; then
ATUIN_HISTORY_ID=__bash_preexec_failure__
return 0
fi
fi fi
local id local id
@ -36,6 +43,17 @@ __atuin_precmd() {
[[ ! $ATUIN_HISTORY_ID ]] && return [[ ! $ATUIN_HISTORY_ID ]] && return
# If the previous preexec hook failed, we manually call __atuin_preexec
if [[ $ATUIN_HISTORY_ID == __bash_preexec_failure__ ]]; then
# This is the command extraction code taken from bash-preexec
local previous_command
previous_command=$(
export LC_ALL=C HISTTIMEFORMAT=''
builtin history 1 | sed '1 s/^ *[0-9][0-9]*[* ] //'
)
__atuin_preexec "$previous_command"
fi
local duration="" local duration=""
if ((BASH_VERSINFO[0] >= 5)); then if ((BASH_VERSINFO[0] >= 5)); then
# We use the high-resolution duration based on EPOCHREALTIME (bash >= # We use the high-resolution duration based on EPOCHREALTIME (bash >=