abo-abo / swiper

Ivy - a generic completion frontend for Emacs, Swiper - isearch with an overview, and more. Oh, man!
https://oremacs.com/swiper/
2.27k stars 337 forks source link

handling `completing-read-multiple` #3014

Open bymoz089 opened 1 year ago

bymoz089 commented 1 year ago

Currently ivy does not handle calls to completing-read-multiple. On those calls Emacs default completion system is used and ivy is utilized only when the user presses the TAB key. But the user has to remember that completing-read-multiple uses , (comma) to separate multiple choices.

How about utilizing ivy (or maybe that belongs into counsel?) on calls to completing-read-multiple right from the start and using ivy-mark feature to let the user choose multiple candidates?

There is no variable to configure invocations of completing-read-multiple in Emacs, like it is done with completing-read and completing-read-function. So an advice is needed. to wrap calls.

A working setup could look like that:

(defun ivy-completing-read-multiple-wrapper (fun prompt table &optional predicate require-match initial-input history def inherit-input-method)
  "a simple wrapper for advicing `completing-read-multiple'."
  (let (choices
        (new-prompt (concat "[multiple] " prompt))) ; just a hint for the user
    (ivy-read new-prompt table
              :predicate predicate
              :require-match require-match
              :initial-input initial-input
              :history history
              :def def
              :action (lambda (x)
                        (if (consp x)
                            (push (car x) choices)
                          (push x choices))))
    choices))

(advice-add 'completing-read-multiple :around #'ivy-completing-read-multiple-wrapper)

Test above functionality with (and compare it with unadviced completing-read-multiple):

(completing-read-multiple "select: "
                          '(("foo" . meh)
                            ("bar" (meeh meeeh))
                            ("moo" . meeeeh))
                          nil
                          t)
;; ⇒ ("moo" "bar")

(completing-read-multiple "select: "
                          '("foo"
                            "bar"
                            "moo")
                          nil
                          t)

;; ⇒ ("moo" "bar")

Is there interest in an PR?