Skip to content

Commit

Permalink
Use PS0 and function substitution in Bash 5.3
Browse files Browse the repository at this point in the history
  • Loading branch information
akinomyoga committed Jan 9, 2025
1 parent d7e8ce8 commit 47d841d
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 9 deletions.
39 changes: 32 additions & 7 deletions bash-preexec.sh
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,15 @@ __bp_preexec_invoke_exec() {
__bp_set_ret_value "$preexec_ret_value" "$__bp_last_argument_prev_command"
}

__bp_invoke_preexec_from_ps0() {
__bp_last_argument_prev_command="${1:-}"

local this_command
__bp_load_this_command_from_history || return

__bp_invoke_preexec_functions "${__bp_last_ret_value:-}" "$__bp_last_argument_prev_command" "$this_command"
}

# This function invokes every function defined in our function array
# "preexec_function". This function receives the arguments $1 and $2 for $?
# and $_, respectively, which will be set for each preexec function. The third
Expand Down Expand Up @@ -320,12 +329,7 @@ __bp_invoke_preexec_functions() {
__bp_set_ret_value "$preexec_ret_value"
}

__bp_install() {
# Exit if we already have this installed.
if [[ "${PROMPT_COMMAND[*]:-}" == *"__bp_precmd_invoke_cmd"* ]]; then
return 1;
fi

__bp_hook_preexec_into_debug() {
local trap_string
trap_string=$(trap -p DEBUG)
trap '__bp_preexec_invoke_exec "$_"' DEBUG
Expand Down Expand Up @@ -355,6 +359,27 @@ __bp_install() {
set -o functrace > /dev/null 2>&1
shopt -s extdebug > /dev/null 2>&1
fi;
}

__bp_hook_preexec_into_ps0() {
# shellcheck disable=SC2016
PS0=${PS0-}'${ __bp_invoke_preexec_from_ps0 "$_"; }'

# Adjust our HISTCONTROL Variable if needed.
__bp_adjust_histcontrol
}

__bp_install() {
# Exit if we already have this installed.
if [[ "${PROMPT_COMMAND[*]:-}" == *"__bp_precmd_invoke_cmd"* ]]; then
return 1;
fi

if (( BASH_VERSINFO[0] > 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] >= 3) )); then
__bp_hook_preexec_into_ps0
else
__bp_hook_preexec_into_debug
fi

local existing_prompt_command
# Remove setting our trap install string and sanitize the existing prompt command string
Expand Down Expand Up @@ -392,7 +417,7 @@ __bp_install() {
# Note: We need to add "trace" attribute to the function so that "trap
# ... DEBUG" inside "__bp_install" takes an effect even when there was an
# existing DEBUG trap.
declare -ft __bp_install
declare -ft __bp_install __bp_hook_preexec_into_debug

# Sets an installation string as part of our PROMPT_COMMAND to install
# after our session has started. This allows bash-preexec to be included
Expand Down
7 changes: 5 additions & 2 deletions test/bash-preexec.bats
Original file line number Diff line number Diff line change
Expand Up @@ -94,8 +94,11 @@ set_exit_code_and_run_precmd() {
bp_install
trap_count_snapshot=$trap_invoked_count

[ "$(trap -p DEBUG | cut -d' ' -f3)" == "'__bp_preexec_invoke_exec" ]
[[ "${preexec_functions[*]}" == *"__bp_original_debug_trap"* ]] || return 1
if (( BASH_VERSINFO[0] < 5 || (BASH_VERSINFO[0] == 5 && BASH_VERSINFO[1] < 3) )); then
# We override the DEBUG trap in Bash < 5.3
[ "$(trap -p DEBUG | cut -d' ' -f3)" == "'__bp_preexec_invoke_exec" ]
[[ "${preexec_functions[*]}" == *"__bp_original_debug_trap"* ]] || return 1
fi

__bp_interactive_mode # triggers the DEBUG trap

Expand Down

0 comments on commit 47d841d

Please sign in to comment.