bash: upgrade to bash-preexec 0.6.0

https://github.com/rcaloras/bash-preexec/releases/tag/0.6.0

This is a small update for us because we've been using a patched version
of this script in Ghostty for some time, and the 0.6.0 release includes
most of the local changes we made as part of maintaining and improving
our bash shell integration.

- https://github.com/rcaloras/bash-preexec/pull/167
- https://github.com/rcaloras/bash-preexec/pull/170

We continue to maintain one local HISTCONTROL-related modification
(#2478). There are a few upstream conversations related to HISTCONTROL
that might eliminate the need for this local patch, so we may revisit
that in the future.
This commit is contained in:
Jon Parise
2025-08-03 09:15:35 -04:00
parent 6b57a23273
commit f4e434fffd

View File

@@ -9,7 +9,7 @@
# Author: Ryan Caloras (ryan@bashhub.com) # Author: Ryan Caloras (ryan@bashhub.com)
# Forked from Original Author: Glyph Lefkowitz # Forked from Original Author: Glyph Lefkowitz
# #
# V0.5.0 # V0.6.0
# #
# General Usage: # General Usage:
@@ -38,7 +38,7 @@
# Make sure this is bash that's running and return otherwise. # Make sure this is bash that's running and return otherwise.
# Use POSIX syntax for this line: # Use POSIX syntax for this line:
if [ -z "${BASH_VERSION-}" ]; then if [ -z "${BASH_VERSION-}" ]; then
return 1; return 1
fi fi
# We only support Bash 3.1+. # We only support Bash 3.1+.
@@ -76,13 +76,13 @@ __bp_install_string=$'__bp_trap_string="$(trap -p DEBUG)"\ntrap - DEBUG\n__bp_in
# Fails if any of the given variables are readonly # Fails if any of the given variables are readonly
# Reference https://stackoverflow.com/a/4441178 # Reference https://stackoverflow.com/a/4441178
__bp_require_not_readonly() { __bp_require_not_readonly() {
local var local var
for var; do for var; do
if ! ( unset "$var" 2> /dev/null ); then if ! ( unset "$var" 2> /dev/null ); then
echo "bash-preexec requires write access to ${var}" >&2 echo "bash-preexec requires write access to ${var}" >&2
return 1 return 1
fi fi
done done
} }
# Remove ignorespace and or replace ignoreboth from HISTCONTROL # Remove ignorespace and or replace ignoreboth from HISTCONTROL
@@ -95,7 +95,7 @@ __bp_adjust_histcontrol() {
# Replace ignoreboth with ignoredups # Replace ignoreboth with ignoredups
if [[ "$histcontrol" == *"ignoreboth"* ]]; then if [[ "$histcontrol" == *"ignoreboth"* ]]; then
histcontrol="ignoredups:${histcontrol//ignoreboth}" histcontrol="ignoredups:${histcontrol//ignoreboth}"
fi; fi
export HISTCONTROL="$histcontrol" export HISTCONTROL="$histcontrol"
} }
@@ -136,7 +136,7 @@ __bp_sanitize_string() {
# It sets a variable to indicate that the prompt was just displayed, # It sets a variable to indicate that the prompt was just displayed,
# to allow the DEBUG trap to know that the next command is likely interactive. # to allow the DEBUG trap to know that the next command is likely interactive.
__bp_interactive_mode() { __bp_interactive_mode() {
__bp_preexec_interactive_mode="on"; __bp_preexec_interactive_mode="on"
} }
@@ -154,7 +154,7 @@ __bp_precmd_invoke_cmd() {
# prompt command" by another precmd execution loop. This avoids infinite # prompt command" by another precmd execution loop. This avoids infinite
# recursion. # recursion.
if (( __bp_inside_precmd > 0 )); then if (( __bp_inside_precmd > 0 )); then
return return
fi fi
local __bp_inside_precmd=1 local __bp_inside_precmd=1
@@ -211,7 +211,7 @@ __bp_preexec_invoke_exec() {
__bp_last_argument_prev_command="${1:-}" __bp_last_argument_prev_command="${1:-}"
# Don't invoke preexecs if we are inside of another preexec. # Don't invoke preexecs if we are inside of another preexec.
if (( __bp_inside_preexec > 0 )); then if (( __bp_inside_preexec > 0 )); then
return return
fi fi
local __bp_inside_preexec=1 local __bp_inside_preexec=1
@@ -289,7 +289,7 @@ __bp_preexec_invoke_exec() {
__bp_install() { __bp_install() {
# Exit if we already have this installed. # Exit if we already have this installed.
if [[ "${PROMPT_COMMAND[*]:-}" == *"__bp_precmd_invoke_cmd"* ]]; then if [[ "${PROMPT_COMMAND[*]:-}" == *"__bp_precmd_invoke_cmd"* ]]; then
return 1; return 1
fi fi
trap '__bp_preexec_invoke_exec "$_"' DEBUG trap '__bp_preexec_invoke_exec "$_"' DEBUG
@@ -300,7 +300,7 @@ __bp_install() {
unset __bp_trap_string unset __bp_trap_string
if [[ -n "$prior_trap" ]]; then if [[ -n "$prior_trap" ]]; then
eval '__bp_original_debug_trap() { eval '__bp_original_debug_trap() {
'"$prior_trap"' '"$prior_trap"'
}' }'
preexec_functions+=(__bp_original_debug_trap) preexec_functions+=(__bp_original_debug_trap)
fi fi
@@ -323,7 +323,7 @@ __bp_install() {
# Set so debug trap will work be invoked in subshells. # Set so debug trap will work be invoked in subshells.
set -o functrace > /dev/null 2>&1 set -o functrace > /dev/null 2>&1
shopt -s extdebug > /dev/null 2>&1 shopt -s extdebug > /dev/null 2>&1
fi; fi
local existing_prompt_command local existing_prompt_command
# Remove setting our trap install string and sanitize the existing prompt command string # Remove setting our trap install string and sanitize the existing prompt command string
@@ -371,7 +371,7 @@ __bp_install_after_session_init() {
if [[ -n "$sanitized_prompt_command" ]]; then if [[ -n "$sanitized_prompt_command" ]]; then
# shellcheck disable=SC2178 # PROMPT_COMMAND is not an array in bash <= 5.0 # shellcheck disable=SC2178 # PROMPT_COMMAND is not an array in bash <= 5.0
PROMPT_COMMAND=${sanitized_prompt_command}$'\n' PROMPT_COMMAND=${sanitized_prompt_command}$'\n'
fi; fi
# shellcheck disable=SC2179 # PROMPT_COMMAND is not an array in bash <= 5.0 # shellcheck disable=SC2179 # PROMPT_COMMAND is not an array in bash <= 5.0
PROMPT_COMMAND+=${__bp_install_string} PROMPT_COMMAND+=${__bp_install_string}
} }
@@ -379,4 +379,4 @@ __bp_install_after_session_init() {
# Run our install so long as we're not delaying it. # Run our install so long as we're not delaying it.
if [[ -z "${__bp_delay_install:-}" ]]; then if [[ -z "${__bp_delay_install:-}" ]]; then
__bp_install_after_session_init __bp_install_after_session_init
fi; fi