@@ -163,6 +163,39 @@ __bp_sanitize_string() {
163
163
fi
164
164
}
165
165
166
+
167
+ # Bash >= 5.1 supports the array version of PROMPT_COMMAND.
168
+ __bp_use_array_prompt_command () {
169
+ (( BASH_VERSINFO[0 ] > 5 || (BASH_VERSINFO[0 ] == 5 && BASH_VERSINFO[1 ] >= 1 ) ))
170
+ }
171
+
172
+
173
+ # Remove $1 and sanitize each elements of PROMPT_COMMAND. We want to keep
174
+ # PROMPT_COMMAND scalar in bash < 5.1 because some configuration tests the
175
+ # support for the array PROMPT_COMMAND by checking the array attribute of
176
+ # PROMPT_COMMAND.
177
+ __bp_remove_command_from_prompt_command () {
178
+ local removed_command=" ${1-} "
179
+ if __bp_use_array_prompt_command; then
180
+ local i sanitized_prompt_command
181
+ for i in " ${! PROMPT_COMMAND[@]} " ; do
182
+ sanitized_prompt_command=" ${PROMPT_COMMAND[i]:- } "
183
+ sanitized_prompt_command=" ${sanitized_prompt_command// " $removed_command " /: } "
184
+ __bp_sanitize_string sanitized_prompt_command " $sanitized_prompt_command "
185
+ if [[ -n " $sanitized_prompt_command " ]]; then
186
+ PROMPT_COMMAND[i]=" $sanitized_prompt_command "
187
+ else
188
+ unset -v ' PROMPT_COMMAND[i]'
189
+ fi
190
+ done
191
+ else
192
+ local sanitized_prompt_command=" ${PROMPT_COMMAND:- } "
193
+ sanitized_prompt_command=" ${sanitized_prompt_command// " $removed_command " /: } " # no-op
194
+ __bp_sanitize_string PROMPT_COMMAND " $sanitized_prompt_command "
195
+ fi
196
+ }
197
+
198
+
166
199
# This function is installed as part of the PROMPT_COMMAND;
167
200
# It sets a variable to indicate that the prompt was just displayed,
168
201
# to allow the DEBUG trap to know that the next command is likely interactive.
@@ -187,6 +220,11 @@ __bp_precmd_invoke_cmd() {
187
220
if (( __bp_inside_precmd > 0 )) ; then
188
221
return
189
222
fi
223
+
224
+ # Check and adjust PROMPT_COMMAND to make sure that PROMPT_COMMAND has the
225
+ # form "__bp_precmd_invoke_cmd; ...; __bp_interactive_mode"
226
+ __bp_install_prompt_command
227
+
190
228
local __bp_inside_precmd=1
191
229
192
230
# Invoke every function defined in our function array.
@@ -354,23 +392,10 @@ __bp_install() {
354
392
shopt -s extdebug > /dev/null 2>&1
355
393
fi ;
356
394
357
- local existing_prompt_command
358
395
# Remove setting our trap install string and sanitize the existing prompt command string
359
- existing_prompt_command=" ${PROMPT_COMMAND:- } "
360
- # Edge case of appending to PROMPT_COMMAND
361
- existing_prompt_command=" ${existing_prompt_command// $__bp_install_string /: } " # no-op
362
- __bp_sanitize_string existing_prompt_command " $existing_prompt_command "
396
+ __bp_remove_command_from_prompt_command " $__bp_install_string "
363
397
364
- # Install our hooks in PROMPT_COMMAND to allow our trap to know when we've
365
- # actually entered something.
366
- PROMPT_COMMAND=' __bp_precmd_invoke_cmd'
367
- PROMPT_COMMAND+=${existing_prompt_command: +$' \n ' $existing_prompt_command }
368
- if (( BASH_VERSINFO[0 ] > 5 || (BASH_VERSINFO[0 ] == 5 && BASH_VERSINFO[1 ] >= 1 ) )) ; then
369
- PROMPT_COMMAND+=(' __bp_interactive_mode' )
370
- else
371
- # shellcheck disable=SC2179 # PROMPT_COMMAND is not an array in bash <= 5.0
372
- PROMPT_COMMAND+=$' \n __bp_interactive_mode'
373
- fi
398
+ __bp_install_prompt_command
374
399
375
400
# Add two functions to our arrays for convenience
376
401
# of definition.
@@ -382,6 +407,38 @@ __bp_install() {
382
407
__bp_interactive_mode
383
408
}
384
409
410
+
411
+ # Encloses PROMPT_COMMAND hooks within __bp_precmd_invoke_cmd and
412
+ # __bp_interactive_mode.
413
+ __bp_install_prompt_command () {
414
+ local prompt_command=" ${PROMPT_COMMAND:- } "
415
+ if __bp_use_array_prompt_command; then
416
+ local IFS=$' \n '
417
+ prompt_command=" ${PROMPT_COMMAND[*]:- } "
418
+ IFS=$' \t\n '
419
+ fi
420
+
421
+ # Exit if we already have a properly set-up hooks in PROMPT_COMMAND
422
+ if [[ " $prompt_command " == __bp_precmd_invoke_cmd$' \n ' * $' \n ' __bp_interactive_mode ]]; then
423
+ return 0
424
+ fi
425
+
426
+ __bp_remove_command_from_prompt_command __bp_precmd_invoke_cmd
427
+ __bp_remove_command_from_prompt_command __bp_interactive_mode
428
+
429
+ # Install our hooks in PROMPT_COMMAND to allow our trap to know when we've
430
+ # actually entered something.
431
+ # shellcheck disable=SC2178 # PROMPT_COMMAND is not an array in bash <= 5.0
432
+ PROMPT_COMMAND=' __bp_precmd_invoke_cmd' ${PROMPT_COMMAND: +$' \n ' $PROMPT_COMMAND }
433
+ if __bp_use_array_prompt_command; then
434
+ PROMPT_COMMAND+=(' __bp_interactive_mode' )
435
+ else
436
+ # shellcheck disable=SC2179 # PROMPT_COMMAND is not an array in bash <= 5.0
437
+ PROMPT_COMMAND+=$' \n __bp_interactive_mode'
438
+ fi
439
+ }
440
+
441
+
385
442
# Sets an installation string as part of our PROMPT_COMMAND to install
386
443
# after our session has started. This allows bash-preexec to be included
387
444
# at any point in our bash profile.
0 commit comments