branch: externals/ivy
commit 7c4fa07ea806e6875e55427a6abedbac28a82bd9
Author: Basil L. Contovounesios <[email protected]>
Commit: Basil L. Contovounesios <[email protected]>
Port to Emacs 31 completing-read-multiple
Until Emacs 30, crm called read-from-minibuffer directly, without
involving Ivy. Since Emacs 31, it calls completing-read, which may
invoke Ivy. But the two are incompatible: Ivy builds the list of
candidates early, before crm has set up its completion table in the
minibuffer; and both need their own keymap active in order to exit
completion with a chosen candidate. The simplest workaround is to
detect crm and toss the hot potato to completing-read-default.
For more discussion, see: #2895, #3014, https://bugs.gnu.org/80296
* ivy.el (ivy--crm-p): New convenience function.
(ivy-completion-in-region): Use it to detect
completing-read-multiple.
(ivy-completing-read): Ditto. Handle completing-read-multiple using
completing-read-default.
---
ivy.el | 35 +++++++++++++++++++++++++----------
1 file changed, 25 insertions(+), 10 deletions(-)
diff --git a/ivy.el b/ivy.el
index 02883d0e82..47b3a36529 100644
--- a/ivy.el
+++ b/ivy.el
@@ -2587,6 +2587,13 @@ This is useful for recursive `ivy-read'."
"Make STR suitable for `format' with no extra arguments."
(ivy--string-replace "%" "%%" str))
+(defun ivy--crm-p (collection)
+ "Return non-nil if completing multiple strings from COLLECTION.
+That is, if we are called from `completing-read-multiple'."
+ ;; It would be nicer to check for `crm-completion-table',
+ ;; but that is local to the minibuffer which may be too late.
+ (eq collection 'crm--collection-fn))
+
;;;###autoload
(defun ivy-completing-read (prompt collection
&optional predicate require-match initial-input
@@ -2607,14 +2614,22 @@ INHERIT-INPUT-METHOD is currently ignored."
(let ((handler
(and (< ivy-completing-read-ignore-handlers-depth (minibuffer-depth))
(assq this-command ivy-completing-read-handlers-alist))))
- (if handler
- (let ((completion-in-region-function #'completion--in-region)
- (ivy-completing-read-ignore-handlers-depth (1+
(minibuffer-depth))))
- (funcall (cdr handler)
- prompt collection
- predicate require-match
- initial-input history
- def inherit-input-method))
+ (cond
+ (handler
+ (let (;; This could also be customizable.
+ (completion-in-region-function #'completion--in-region)
+ (ivy-completing-read-ignore-handlers-depth (1+
(minibuffer-depth))))
+ (funcall (cdr handler)
+ prompt collection predicate require-match
+ initial-input history def inherit-input-method)))
+ ((ivy--crm-p collection)
+ ;; Ivy is currently incompatible with `completing-read-multiple'.
+ ;; This was harmless while crm called `read-from-minibuffer'
+ ;; directly; but since Emacs 31 it uses `completing-read':
+ ;; `https://bugs.gnu.org/80296'.
+ (completing-read-default prompt collection predicate require-match
+ initial-input history def inherit-input-method))
+ (t
;; See the doc of `completing-read'.
(when (consp history)
(when (numberp (cdr history))
@@ -2647,7 +2662,7 @@ INHERIT-INPUT-METHOD is currently ignored."
;; For `completing-read' compat, return the first element of
;; DEFAULT, if it is a list; "", if DEFAULT is nil; or DEFAULT.
(or def "")
- str)))))
+ str))))))
(defun ivy-completing-read-with-empty-string-def
(prompt collection
@@ -2782,7 +2797,7 @@ See `completion-in-region' for further information."
(completion--done str 'finished "Sole match"))
t)
(t
- (when (eq collection 'crm--collection-fn)
+ (when (ivy--crm-p collection)
(setq comps (delete-dups comps)))
(let ((initial (substring str base-size))
(base-pos (+ start base-size)))