branch: elpa/bash-completion commit a96525afd9077c06d781c59e78bfc6620e41be8f Author: Stephane Zermatten <szerm...@gmx.net> Commit: Stephane Zermatten <szerm...@gmx.net>
fix: Recover $? after completion. Before this change, the value of $? was lost when doing a completion as it required running a command, so $? became the status code of the completion command. So if you typed: > false > ech<TAB> $? You would get 0 instead of 1, set by false. This change stores the value of $? first thing before executing any command, then have __ebcret restore it. The status code that bash completion, the one that's embedded in the next prompt, remains the status code of the completion command, but $? is the status code of the last user command, before completion was run. issue #77 --- bash-completion.el | 22 ++++++++++----------- test/bash-completion-integration-test.el | 34 ++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 11 deletions(-) diff --git a/bash-completion.el b/bash-completion.el index 130152fbb4..5a7d9ff8fe 100644 --- a/bash-completion.el +++ b/bash-completion.el @@ -294,7 +294,7 @@ Bash processes.") (defconst bash-completion-special-chars "[ -$&-*,:-<>?[-^`{-}]" "Regexp of characters that must be escaped or quoted.") -(defconst bash-completion--ps1 "'==emacs==ret=$?==.'" +(defconst bash-completion--ps1 "'==emacs==ret=${__ebcret:-$?}==.'" "Value for the special PS1 prompt set for completions, quoted.") (eval-when-compile @@ -1532,12 +1532,12 @@ Return the status code of the command, as a number." ;; single process, assume __ebcpre is already defined ((not define-functions) (concat - "if type __ebcpre &>/dev/null; then " + "__ebcor=$?; if type __ebcpre &>/dev/null; then " " __ebcpre; %s; __ebcret $?; " "else " " echo ==emacs==nopre=${BASH_VERSION}==.; " - " __ebcp=(\"$PS1\" \"$PROMPT_COMMAND\");" - " unset PS1 PROMPT_COMMAND;" + " __ebcp=(\"$PS1\" \"$PROMPT_COMMAND\" $__ebcor);" + " unset PS1 PROMPT_COMMAND __ebcor;" "fi;\n")) ;; single process, define __ebcpre (t @@ -1549,23 +1549,23 @@ Return the status code of the command, as a number." " fi;" " history -d $c &>/dev/null || true;" "} ; function __ebcret {" - " __ebcret=t;" - " return $1;" + " __ebcret=$1;" + " return ${__ebcp[2]};" "} ; function __ebctrap {" - " if [[ \"$__ebcret\" = \"t\" && ${#__ebcp[@]} -gt 0 ]]; then" + " if [[ -n \"$__ebcret\" && ${#__ebcp[@]} -gt 0 ]]; then" " PS1=\"${__ebcp[0]}\";" " PROMPT_COMMAND=\"${__ebcp[1]}\";" - " unset __ebcp;" - " unset __ebcret;" + " unset __ebcp __ebcret;" " fi;" "} ; trap __ebctrap DEBUG ; function __ebcpre {" + " __ebcor=${__ebcor:-$?}; " " set +x; set +o emacs; set +o vi;" " echo \"==emacs==bash=${BASH_VERSION}==.\";" " if [[ ${#__ebcp[@]} = 0 ]]; then " - " __ebcp=(\"$PS1\" \"$PROMPT_COMMAND\");" + " __ebcp=(\"$PS1\" \"$PROMPT_COMMAND\" $__ebcor);" " fi;" " PS1=" bash-completion--ps1 ";" - " unset PROMPT_COMMAND;" + " unset PROMPT_COMMAND __ebcor;" " __ebcnohistory 1;" "} ; { __ebcpre; %s; __ebcret $?; }\n"))) commandline))) diff --git a/test/bash-completion-integration-test.el b/test/bash-completion-integration-test.el index f57ddc7865..02c24ecc0d 100644 --- a/test/bash-completion-integration-test.el +++ b/test/bash-completion-integration-test.el @@ -926,4 +926,38 @@ $ "))))) (should (equal (bash-completion_test-buffer-string) "$ dummy dummy\n--$ --\n$ dummy dummy\n--$ --\n$ ")))) +(ert-deftest bash-completion-integration-recover-status-code () + (bash-completion_test-with-shell-harness + (concat ; .bashrc + "function failwith { return $1; }\n" + "function dummy { echo $?; }\n" + "function _dummy {\n" + " COMPREPLY=( dummy )\n" + "}\n" + "complete -F _dummy dummy\n" + "PS1='\$ '") + nil + ;; The first time initializes completion, the second time executes + ;; an already initialized completion. The two cases behave very + ;; differently, so we test both. + (dotimes (i 2) + (bash-completion_test-send (format "failwith %s" (+ 100 i))) + (should (equal + "dummy dummy " + (bash-completion_test-complete "dummy dum"))) + (let ((start (line-beginning-position))) + (comint-send-input) + (bash-completion_test-wait-for-prompt start))) + ;; The status code printed by the dummy function should be the one + ;; from testfail, so 123, and not the one from the completion + ;; command executed to do completion for the dummy function. + (should (equal (bash-completion_test-buffer-string) + (concat "$ failwith 100\n" + "$ dummy dummy\n" + "100\n" + "$ failwith 101\n" + "$ dummy dummy\n" + "101\n" + "$ "))))) + ;;; bash-completion-integration-test.el ends here