Fix 'in prompt command'. Don't eval PROMPT_COMMAND

- Need to update unit tests for echos on both cases
- Small edge case where preexec is not invoked the first time if
PROMPT_COMMAND is appended to after bash-preexec is sourced.
- Handle cases where we append with semicolon and \n
This commit is contained in:
Ryan Caloras 2020-08-21 21:57:14 -04:00
parent c4c69c4337
commit c0fb0c02de
2 changed files with 37 additions and 6 deletions

View file

@ -152,7 +152,7 @@ __bp_set_ret_value() {
__bp_in_prompt_command() {
local prompt_command_array
IFS=';' read -ra prompt_command_array <<< "$PROMPT_COMMAND"
IFS=$'\n;' read -rd '' -a prompt_command_array <<< "$PROMPT_COMMAND"
local trimmed_arg
trimmed_arg=$(__bp_trim_whitespace "${1:-}")
@ -175,6 +175,7 @@ __bp_in_prompt_command() {
# environment to attempt to detect if the current command is being invoked
# interactively, and invoke 'preexec' if so.
__bp_preexec_invoke_exec() {
# Save the contents of $_ so that it can be restored later on.
# https://stackoverflow.com/questions/40944532/bash-preserve-in-a-debug-trap#40944702
__bp_last_argument_prev_command="${1:-}"
@ -295,7 +296,7 @@ __bp_install() {
local __bp_existing_prompt_command
# Remove setting our trap install string and sanitize the existing prompt command string
__bp_existing_prompt_command="${PROMPT_COMMAND//$__bp_install_string;}" # Edge case of appending to PROMPT_COMMAND with ';'
__bp_existing_prompt_command="${PROMPT_COMMAND//$__bp_install_string[;$'\n']}" # Edge case of appending to PROMPT_COMMAND
__bp_existing_prompt_command="${__bp_existing_prompt_command//$__bp_install_string}"
__bp_existing_prompt_command=$(__bp_sanitize_string "$__bp_existing_prompt_command")
@ -312,8 +313,9 @@ __bp_install() {
precmd_functions+=(precmd)
preexec_functions+=(preexec)
# Since this function is invoked via PROMPT_COMMAND, re-execute PC now that it's properly set
eval "$PROMPT_COMMAND"
# Invoke our two functions manually that were added to $PROMPT_COMMAND
__bp_precmd_invoke_cmd
__bp_interactive_mode
}
# Sets an installation string as part of our PROMPT_COMMAND to install

View file

@ -111,14 +111,43 @@ test_preexec_echo() {
PROMPT_COMMAND="echo before"
PROMPT_COMMAND="$PROMPT_COMMAND; echo before2"
__bp_install_after_session_init
PROMPT_COMMAND="$PROMPT_COMMAND; echo after"
PROMPT_COMMAND="$PROMPT_COMMAND"$'\n echo after'
PROMPT_COMMAND="echo after2; $PROMPT_COMMAND;"
eval "$PROMPT_COMMAND"
expected_result=$'__bp_precmd_invoke_cmd\necho after2; echo before; echo before2\n echo after\n__bp_interactive_mode'
[ "$PROMPT_COMMAND" == "$expected_result" ]
}
@test "Adding to PROMPT_COMMAND after with semicolon" {
PROMPT_COMMAND="echo before"
__bp_install_after_session_init
PROMPT_COMMAND="$PROMPT_COMMAND; echo after"
eval "$PROMPT_COMMAND"
expected_result=$'__bp_precmd_invoke_cmd\necho before\n echo after\n__bp_interactive_mode'
[ "$PROMPT_COMMAND" == "$expected_result" ]
}
@test "during install PROMPT_COMMAND and precmd functions should be executed each once" {
PROMPT_COMMAND="echo before"
PROMPT_COMMAND="$PROMPT_COMMAND; echo before2"
__bp_install_after_session_init
PROMPT_COMMAND="$PROMPT_COMMAND; echo after"
PROMPT_COMMAND="echo after2; $PROMPT_COMMAND;"
precmd() { echo "inside precmd"; }
run eval "$PROMPT_COMMAND"
[ "${lines[0]}" == "after2" ]
[ "${lines[1]}" == "before" ]
[ "${lines[2]}" == "before2" ]
[ "${lines[3]}" == "inside precmd" ]
[ "${lines[4]}" == "after" ]
[ "${#lines[@]}" == '5' ]
}
@test "No functions defined for preexec should simply return" {
__bp_interactive_mode
@ -257,7 +286,7 @@ test_preexec_echo() {
@test "in_prompt_command should detect if a command is part of PROMPT_COMMAND" {
PROMPT_COMMAND="precmd_invoke_cmd; something;"
PROMPT_COMMAND=$'precmd_invoke_cmd\n something; echo yo\n __bp_interactive_mode'
run '__bp_in_prompt_command' "something"
[ $status -eq 0 ]