branch: elpa/bash-completion commit 762f28fefba487e15d626691310f3194804eb71a Author: Stephane Zermatten <szerm...@gmx.net> Commit: Stephane Zermatten <szerm...@gmx.net>
fix: Avoid commands in PS1 causing issues. With the fix of issue #79, PS1 is displayed after the bash completion mark, but later on ignored. This doesn't work if PS1 executes commands, as the command execution will trigger the TRAP. This change evaluates PS1 beforehand, so it won't confuse the trap. With this approach, an outdated PS1 may be displayed after a Bash syntax error, but this is temporary, as executing any command fixes it. issue #80 --- bash-completion.el | 23 +++++++------ test/bash-completion-integration-test.el | 55 ++++++++++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 12 deletions(-) diff --git a/bash-completion.el b/bash-completion.el index d82958cae9..d3f002b4e3 100644 --- a/bash-completion.el +++ b/bash-completion.el @@ -1536,7 +1536,7 @@ Return the status code of the command, as a number." " __ebcpre; %s; __ebcret $?; " "else " " echo ==emacs==nopre=${BASH_VERSION}==.; " - " __ebcp=(\"$PS1\" \"${__ebcpc:-$PROMPT_COMMAND}\" $__ebcor);" + " __ebcp=(\"$PS1\" \"$PROMPT_COMMAND\" $__ebcor);" " unset PS1 PROMPT_COMMAND __ebcor;" "fi;\n")) ;; single process, define __ebcpre @@ -1549,16 +1549,16 @@ Return the status code of the command, as a number." " fi;" " history -d $c &>/dev/null || true;" "} ; function __ebcret {" - " local r=$1 e=${__ebcp[2]};" - " PS1=\"${__ebcp[0]}\";" - " __ebcpc=\"${__ebcp[1]}\";" - " unset __ebcp;" - " echo \"==emacs==ret=$r==.\";" - " return $e;" + " PS1=\"$(eval \"echo \\\"${__ebcp[0]}\\\"\")\";" + " echo >>/tmp/debug \">>$PS1<<\";" + " __ebcret=$1;" + " echo \"==emacs==ret=${__ebcret}==.\";" + " return ${__ebcp[2]};" "} ; function __ebctrap {" - " if [[ ${#__ebcpc} -gt 0 ]]; then" - " PROMPT_COMMAND=\"${__ebcpc}\";" - " unset __ebcpc;" + " if [[ -n \"$__ebcret\" && ${#__ebcp[@]} -gt 0 ]]; then" + " PS1=\"${__ebcp[0]}\";" + " PROMPT_COMMAND=\"${__ebcp[1]}\";" + " unset __ebcp __ebcret;" " fi;" "} ; " "if [[ \"$(trap -p DEBUG)\" =~ trap\\ --\\ \\'(.*)\\'\\ DEBUG ]]; then " @@ -1571,9 +1571,8 @@ Return the status code of the command, as a number." " set +x; set +o emacs; set +o vi;" " echo \"==emacs==bash=${BASH_VERSION}==.\";" " if [[ ${#__ebcp[@]} = 0 ]]; then " - " __ebcp=(\"$PS1\" \"${__ebcpc:-$PROMPT_COMMAND}\" $__ebcor);" + " __ebcp=(\"$PS1\" \"${PROMPT_COMMAND}\" $__ebcor);" " fi;" - ;;" PS1='==emacs==prompt=1==.';" " unset PS1 PROMPT_COMMAND __ebcor;" " __ebcnohistory 1;" "} ; { __ebcpre; %s; __ebcret $?; }\n"))) diff --git a/test/bash-completion-integration-test.el b/test/bash-completion-integration-test.el index 02c24ecc0d..6fb3fb2026 100644 --- a/test/bash-completion-integration-test.el +++ b/test/bash-completion-integration-test.el @@ -960,4 +960,59 @@ $ "))))) "101\n" "$ "))))) +(ert-deftest bash-completion-keep-existing-trap () + (bash-completion_test-with-shell-harness + (concat ; .bashrc + "calls=0\n" + "function _calltrap {\n" + " calls=$((calls+1))\n" + "}\n" + "trap _calltrap DEBUG\n" + "PS1='\$ '") + nil + (bash-completion_test-send "n=$calls") + (bash-completion_test-send "tru" 'complete) + (bash-completion_test-send "fals" 'complete) + (bash-completion_test-send "[[ $calls -gt $n ]] && echo ok") + (bash-completion_test-send "trap -p DEBUG") + (should (equal (bash-completion_test-buffer-string) + (concat + "$ n=$calls\n" + "$ true\n" + "$ false\n" + "$ [[ $calls -gt $n ]] && echo ok\n" + "ok\n" + "$ trap -p DEBUG\n" + "trap -- '_calltrap; __ebctrap' DEBUG\n" + "$ "))))) + +(ert-deftest bash-completion-prompt-after-syntax-error-issue-79 () + (bash-completion_test-with-shell-harness + (concat ; .bashrc + "PS1='\$ '") + nil + (goto-char (point-max)) + (let ((start (point))) + (insert "function foobar") + (completion-at-point) + (insert " {}") + (comint-send-input) + (bash-completion_test-wait-for-prompt start)))) + +(ert-deftest bash-completion-command-in-prompt-issue-80 () + (bash-completion_test-with-shell-harness + (concat ; .bashrc + "PS1='`echo boo`$ '") + nil + (goto-char (point-max)) + (let ((start (point))) + (should + (equal + "function " + (bash-completion_test-complete "functi"))) + (bash-completion_test-wait-for-prompt start)) + (should (equal (bash-completion_test-buffer-string) + (concat + "boo$ function"))))) + ;;; bash-completion-integration-test.el ends here