Subject: Re: bug#76010: describe-face and minibuffer-next/previous-completion

From: Dmitry Gutov <[email-masked]>
Date: Tue, 11 Feb 2025 07:00:51 +0200

Hi Juri,

On 03/02/2025 09:44, Juri Linkov wrote:
>>> emacs -Q
>>> M-x describe-face RET
>>> M-<down> M-<down> M-<down>
>>>
>>> In the minibuffer prompt, I see the completions have accumulated.
>>> I.e. it appears as
>>> boldblink-matching-paren-offscreenabbrev-table-name
>>> instead of the expected
>>> bold
>>> which is the currently highlighted completion candidate.
>>> The same accumulation occurs when M-<up> (minibuffer-previous-completion) is used.
>> Thanks.
>>
>> Juri, this seems to be a regression since Emacs 29, so could you
>> please look into this soon?
> It seems that removal of completion-base-affixes
> and completion-use-base-affixes in bug#48356 broke
> completing-read-multiple.

Could you try this patch?

It seems to handle the described scenario well, but maybe I'm missing 
some other case.

E.g. when would the current implementation go down the "else" path, 
after (and (stringp start) (stringp end)) evaluating to nil?

diff --git a/lisp/emacs-lisp/crm.el b/lisp/emacs-lisp/crm.el
index 454c3e85074..a371a8e14de 100644
--- a/lisp/emacs-lisp/crm.el
+++ b/lisp/emacs-lisp/crm.el
@@ -251,22 +251,16 @@ completing-read-multiple
           (setq-local minibuffer-completion-table #'crm--collection-fn)
           (setq-local minibuffer-completion-predicate predicate)
           (setq-local completion-list-insert-choice-function
-                      (lambda (start end choice)
-                        (if (and (stringp start) (stringp end))
-                            (let* ((beg (save-excursion
-                                          (goto-char (minibuffer-prompt-end))
-                                          (or (search-forward start nil t)
-                                              (search-forward-regexp crm-separator nil t)
-                                              (minibuffer-prompt-end))))
-                                   (end (save-excursion
-                                          (goto-char (point-max))
-                                          (or (search-backward end nil t)
-                                              (progn
-                                                (goto-char beg)
-                                                (search-forward-regexp crm-separator nil t))
-                                              (point-max)))))
-                              (completion--replace beg end choice))
-                          (completion--replace start end choice))))
+                      (lambda (_start _end choice)
+                        (let* ((beg (save-excursion
+                                      (if (search-backward-regexp crm-separator nil t)
+                                          (1+ (point))
+                                        (minibuffer-prompt-end))))
+                               (end (save-excursion
+                                      (if (search-forward-regexp crm-separator nil t)
+                                          (1- (point))
+                                        (point-max)))))
+                          (completion--replace beg end choice))))
           ;; see completing_read in src/minibuf.c
           (setq-local minibuffer-completion-confirm
                       (unless (eq require-match t) require-match))