Subject: bug#21644: 24.4; completing-read acts differently on functional collection

From: Oleh Krehel <[email-masked]>
Date: Thu, 08 Oct 2015 12:13:22 +0200

> Try typing "g" followed by RET for both of the above. In the first
> case (collection is a list), it returns "green". In the second case
> (collection is a function), it returns just "g". This is reproducible
> in emacs -Q.

I can reproduce this as well, although "TAB RET" works where "RET"
doesn't. I attach a patch with a fix. If someone can check it I can push
it. The patch doesn't solve all the intricacies of
`completion-ignore-case' that were mentioned in that function's
comments, just this specific use case.

    Oleh

>From 6eca5cbbe328bc035fff41d33b47f03ac5b6ca81 Mon Sep 17 00:00:00 2001
From: Oleh Krehel <[email-masked]>
Date: Thu, 8 Oct 2015 12:05:20 +0200
Subject: [PATCH] lisp/minibuffer.el (completion--complete-and-exit): Fix
 (bug#21644)

When `test-completion' returns a string and `completion-ignore-case'
is nil, the result was not used at all and only the minibuffer text
was returned. This change makes it use that returned string.
---
 lisp/minibuffer.el | 96 ++++++++++++++++++++++++++++--------------------------
 1 file changed, 49 insertions(+), 47 deletions(-)

diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 2814d02..f684164 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -1342,56 +1342,58 @@ completion-complete-and-exit
        (_ nil)))))
 
 (defun completion--complete-and-exit (beg end
-                                          exit-function completion-function)
+                                      exit-function completion-function)
   "Exit from `require-match' minibuffer.
 COMPLETION-FUNCTION is called if the current buffer's content does not
 appear to be a match."
-    (cond
-     ;; Allow user to specify null string
-   ((= beg end) (funcall exit-function))
-     ((test-completion (buffer-substring beg end)
-                       minibuffer-completion-table
-                       minibuffer-completion-predicate)
-      ;; FIXME: completion-ignore-case has various slightly
-      ;; incompatible meanings.  E.g. it can reflect whether the user
-      ;; wants completion to pay attention to case, or whether the
-      ;; string will be used in a context where case is significant.
-      ;; E.g. usually try-completion should obey the first, whereas
-      ;; test-completion should obey the second.
-      (when completion-ignore-case
-        ;; Fixup case of the field, if necessary.
-        (let* ((string (buffer-substring beg end))
-               (compl (try-completion
-                       string
-                       minibuffer-completion-table
-                       minibuffer-completion-predicate)))
-          (when (and (stringp compl) (not (equal string compl))
-                     ;; If it weren't for this piece of paranoia, I'd replace
-                     ;; the whole thing with a call to do-completion.
-                     ;; This is important, e.g. when the current minibuffer's
-                     ;; content is a directory which only contains a single
-                     ;; file, so `try-completion' actually completes to
-                     ;; that file.
-                     (= (length string) (length compl)))
-            (completion--replace beg end compl))))
-      (funcall exit-function))
-
-     ((memq minibuffer-completion-confirm '(confirm confirm-after-completion))
-      ;; The user is permitted to exit with an input that's rejected
-      ;; by test-completion, after confirming her choice.
-      (if (or (eq last-command this-command)
-              ;; For `confirm-after-completion' we only ask for confirmation
-              ;; if trying to exit immediately after typing TAB (this
-              ;; catches most minibuffer typos).
-              (and (eq minibuffer-completion-confirm 'confirm-after-completion)
-                   (not (memq last-command minibuffer-confirm-exit-commands))))
-        (funcall exit-function)
-        (minibuffer-message "Confirm")
-        nil))
-
-     (t
-      ;; Call do-completion, but ignore errors.
-      (funcall completion-function))))
+  (cond
+    ;; Allow user to specify null string
+    ((= beg end) (funcall exit-function))
+    ((test-completion (buffer-substring beg end)
+                      minibuffer-completion-table
+                      minibuffer-completion-predicate)
+     (let* ((string (buffer-substring beg end))
+            (compl (try-completion
+                    string
+                    minibuffer-completion-table
+                    minibuffer-completion-predicate)))
+       (when (and (stringp compl)
+                  (or (not completion-ignore-case)
+                      ;; FIXME: completion-ignore-case has various slightly
+                      ;; incompatible meanings.  E.g. it can reflect whether the user
+                      ;; wants completion to pay attention to case, or whether the
+                      ;; string will be used in a context where case is significant.
+                      ;; E.g. usually try-completion should obey the first, whereas
+                      ;; test-completion should obey the second.d
+
+                      ;; Fixup case of the field, if necessary.
+                      (and (not (equal string compl))
+                           ;; If it weren't for this piece of paranoia, I'd replace
+                           ;; the whole thing with a call to do-completion.
+                           ;; This is important, e.g. when the current minibuffer's
+                           ;; content is a directory which only contains a single
+                           ;; file, so `try-completion' actually completes to
+                           ;; that file.
+                           (= (length string) (length compl)))))
+         (completion--replace beg end compl)))
+     (funcall exit-function))
+
+    ((memq minibuffer-completion-confirm '(confirm confirm-after-completion))
+     ;; The user is permitted to exit with an input that's rejected
+     ;; by test-completion, after confirming her choice.
+     (if (or (eq last-command this-command)
+             ;; For `confirm-after-completion' we only ask for confirmation
+             ;; if trying to exit immediately after typing TAB (this
+             ;; catches most minibuffer typos).
+             (and (eq minibuffer-completion-confirm 'confirm-after-completion)
+                  (not (memq last-command minibuffer-confirm-exit-commands))))
+         (funcall exit-function)
+       (minibuffer-message "Confirm")
+       nil))
+
+    (t
+     ;; Call do-completion, but ignore errors.
+     (funcall completion-function))))
 
 (defun completion--try-word-completion (string table predicate point md)
   (let ((comp (completion-try-completion string table predicate point md)))
-- 
2.6.1