diff --git a/lisp/pcomplete.el b/lisp/pcomplete.el index d5ffee6ce42..121f4efdb92 100644 --- a/lisp/pcomplete.el +++ b/lisp/pcomplete.el @@ -1376,7 +1376,7 @@ OPTIONS should be a list of option strings; if a string ends in \"=\", it's an option that accepts a value." (lambda (string pred action) (pcase action - ('nil ; try-completion + ('nil ; try-completion (let ((result (try-completion string options pred))) ;; If the completion ends in "=", then it's not really ;; complete yet: we expect a value after the "=". Return the @@ -1385,10 +1385,22 @@ OPTIONS should be a list of option strings; if a string ends in (if (and (eq result t) (string-suffix-p "=" string)) string result))) - ('t ; all-completions - (all-completions string options pred)) - ('lambda ; test-completion - (test-completion string options pred))))) + ('t ; all-completions + ;; Don't list completions when the boundary starts after an "=". + (unless (and (string-suffix-p "=" string) + (member string options)) + (all-completions string options pred))) + ('lambda ; test-completion + (test-completion string options pred)) + (`(boundaries . ,suffix) ; completion-boundaries + ;; As above, if the completion ends in "=", then it's not + ;; complete yet. The completion's boundary should start after + ;; the "=" to indicate that that's where subsequent completions + ;; will occur. + (if (and (string-suffix-p "=" string) + (member string options)) + `(boundaries ,(length string) . ,(length suffix)) + (completion-boundaries string options pred suffix)))))) ;;; Parsing help messages diff --git a/test/lisp/pcomplete-tests.el b/test/lisp/pcomplete-tests.el index a5357f18835..95432442cc6 100644 --- a/test/lisp/pcomplete-tests.el +++ b/test/lisp/pcomplete-tests.el @@ -96,17 +96,21 @@ usage: git [-v | --version] [-h | --help] [-C ] [-c =] #("--super-prefix=" 0 1 (pcomplete-annotation "")) #("--config-env=" 0 1 (pcomplete-annotation ""))))))) -(defun pcomplete-shell-completion (input) - "Insert INPUT into shell mode, run completion, and return the result." - (with-temp-buffer - (shell (current-buffer)) - (unwind-protect - (let ((start (point))) - (insert input) - (completion-at-point) - (buffer-substring start (point))) - (let (kill-buffer-query-functions) - (kill-buffer (current-buffer)))))) +(defmacro pcomplete-shell-completion (input &rest body) + "Insert INPUT into shell mode, run completion, and return the result. +BODY is a list of extra forms to call after completion (e.g. to choose a +completion from the minibuffer)." + (declare (indent 1)) + `(with-temp-buffer + (shell (current-buffer)) + (unwind-protect + (let ((start (point))) + (insert ,input) + (completion-at-point) + ,@body + (buffer-substring start (point))) + (let (kill-buffer-query-functions) + (kill-buffer (current-buffer)))))) (defun pcomplete/pcmpl-option-test () "Completion for a test command taking long options." @@ -124,5 +128,21 @@ usage: git [-v | --version] [-h | --help] [-C ] [-c =] (should (string= (pcomplete-shell-completion "pcmpl-option-test --ver") "pcmpl-option-test --version "))) +(ert-deftest pcomplete-test-long-options/with-value/multiple () + "Test that completing long options taking values doesn't insert a space. +This tests completing when there are multiple possibilities." + (should (string= (pcomplete-shell-completion "pcmpl-option-test --" + (minibuffer-next-completion 1) + (minibuffer-choose-completion)) + "pcmpl-option-test --owner="))) + +(ert-deftest pcomplete-test-long-options/without-value/multiple () + "Test that completing long options without values inserts a space. +This tests completing when there are multiple possibilities." + (should (string= (pcomplete-shell-completion "pcmpl-option-test --" + (minibuffer-next-completion 2) + (minibuffer-choose-completion)) + "pcmpl-option-test --version "))) + (provide 'pcomplete-tests) ;;; pcomplete-tests.el ends here