emacs-31 61700f9dd64: Fix TAB to wrap with completion-auto-select t

Sean Whitton <[email protected]>
Newsgroups gmane.emacs.diffs
Message-ID <[email protected]>
branch: emacs-31
commit 61700f9dd646767b5d81b1835822c5d112051604
Author: Spencer Baugh <[email protected]>
Commit: Sean Whitton <[email protected]>

    Fix TAB to wrap with completion-auto-select t
    
    * lisp/minibuffer.el (completions--clear-selection): New
    function.
    (minibuffer-hide-completions): Call it.
    * lisp/simple.el (next-column-completion): Call it (bug#81635).
    * test/lisp/minibuffer-tests.el
    (completion-auto-select-test-bug81635): New test.
---
 lisp/minibuffer.el            |  9 ++++++++-
 lisp/simple.el                |  8 +++++---
 test/lisp/minibuffer-tests.el | 33 +++++++++++++++++++++++++++++++++
 3 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 2019fe5299d..3d1fb7c6b81 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -2742,6 +2742,13 @@ The candidate will still be chosen by `choose-completion' unless
     (goto-char (or (next-single-property-change (point) 'completion--string)
                    (point-max)))))
 
+(defun completions--clear-selection ()
+  "Clear the selected candidate in the completions buffer.
+
+Unlike `completions--deselect' this fully clears all selected-completion
+state from the buffer."
+  (goto-char (point-min)))
+
 (defun completions--should-show-p (metadata &optional force-eager-update)
   "Return non-nil if *Completions* should be automatically updated or displayed.
 
@@ -3020,7 +3027,7 @@ has been requested by the completion table."
     (with-selected-window win
       ;; Move point off any completions, so we don't move point there
       ;; again the next time `minibuffer-completion-help' is called.
-      (goto-char (point-min))
+      (completions--clear-selection)
       (bury-buffer))))
 
 (defun exit-minibuffer ()
diff --git a/lisp/simple.el b/lisp/simple.el
index 21a4ae65b40..af986e07f55 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -10269,7 +10269,9 @@ Also see the `completion-auto-wrap' variable."
                          (not (eq completions-format 'vertical))))
             (if (and (eq completion-auto-select t) tabcommand
                      (minibufferp completion-reference-buffer))
-                (throw 'bound nil)
+                (progn
+                  (completions--clear-selection)
+                  (throw 'bound nil))
               (first-completion))))
         (when (and (eq completions-format 'vertical)
                    (or last
@@ -10321,8 +10323,8 @@ Also see the `completion-auto-wrap' variable."
                    (completion--move-to-candidate-start))
                   ((and (eq completion-auto-select t) tabcommand
                         (minibufferp completion-reference-buffer))
-                   (progn
-                     (throw 'bound nil)))
+                   (completions--clear-selection)
+                   (throw 'bound nil))
                   (t
                    (last-completion)))))
         (setq n (1+ n))))
diff --git a/test/lisp/minibuffer-tests.el b/test/lisp/minibuffer-tests.el
index 2f70d248711..ecf1cde61ad 100644
--- a/test/lisp/minibuffer-tests.el
+++ b/test/lisp/minibuffer-tests.el
@@ -639,6 +639,39 @@
       (execute-kbd-macro (kbd "TAB TAB"))
       (should (eq (current-buffer) (get-buffer "*Completions*"))))))
 
+(ert-deftest completion-auto-select-test-bug81635 ()
+  (let ((completion-auto-select t)
+        (completion-auto-wrap t))
+    (completing-read-with-minibuffer-setup
+        '("aa" "ab" "ac")
+      (cl-flet ((selected ()
+                  (and (eq (current-buffer) (get-buffer "*Completions*"))
+                       (get-text-property (point) 'completion--string))))
+        ;; TAB cycles forward through all candidates, then to the
+        ;; minibuffer, then back to the first candidate.
+        (execute-kbd-macro (kbd "a TAB"))
+        (should (equal (selected) "aa"))
+        (execute-kbd-macro (kbd "TAB"))
+        (should (equal (selected) "ab"))
+        (execute-kbd-macro (kbd "TAB"))
+        (should (equal (selected) "ac"))
+        (execute-kbd-macro (kbd "TAB"))
+        (should (minibufferp))
+        (execute-kbd-macro (kbd "TAB"))
+        (should (equal (selected) "aa"))
+        (execute-kbd-macro (kbd "TAB"))
+        (should (equal (selected) "ab"))
+        ;; S-TAB cycles backward, then to the minibuffer, then to the
+        ;; last candidate.
+        (execute-kbd-macro (kbd "<backtab>"))
+        (should (equal (selected) "aa"))
+        (execute-kbd-macro (kbd "<backtab>"))
+        (should (minibufferp))
+        (execute-kbd-macro (kbd "<backtab>"))
+        (should (equal (selected) "ac"))
+        (execute-kbd-macro (kbd "<backtab>"))
+        (should (equal (selected) "ab"))))))
+
 (ert-deftest completion-auto-wrap-test ()
   (let ((completion-auto-wrap nil))
     (completing-read-with-minibuffer-setup
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.