]> git.eshelyaron.com Git - emacs.git/commitdiff
Adjust completion un/requoting in 'completing-read-multiple'
authorEshel Yaron <me@eshelyaron.com>
Mon, 22 Jan 2024 14:02:19 +0000 (15:02 +0100)
committerEshel Yaron <me@eshelyaron.com>
Mon, 22 Jan 2024 14:02:19 +0000 (15:02 +0100)
Teach 'completing-read-multiple' about 'completion--unquote', so it
can be used with completion tables that perform quoting.  Namely, this
allows reading multiple file names with:

  (completing-read-multiple "Files: " #'completion--file-name-table)

* lisp/emacs-lisp/crm.el (crm--table): New helper function.
(completing-read-multiple): Use it.

lisp/emacs-lisp/crm.el

index 32221047c20ce43f0784db2987ed84dcfaa81880..b71475e0b374a73b4a00dff6b87835fe87a76565 100644 (file)
@@ -341,6 +341,49 @@ that fails this command prompts you for the separator to use."
           (seq-filter (lambda (ov) (overlay-get ov 'crm-separator))
                       (overlays-in (minibuffer-prompt-end) (point-max))))))
 
+(defun crm--table (table s p a)
+  (let ((beg 0))
+    (while (string-match crm-current-separator s beg)
+      (setq beg (match-end 0)))
+    (pcase a
+      (`(boundaries . ,suffix)
+       (let ((bounds (completion-boundaries
+                      (substring s beg) table p
+                      (substring suffix 0
+                                 (string-match crm-current-separator
+                                               suffix)))))
+         `(boundaries ,(+ (car bounds) beg) . ,(cdr bounds))))
+      ('metadata (completion-metadata (substring s beg) table p))
+      ('nil (let ((comp (complete-with-action a table (substring s beg) p)))
+              (if (stringp comp) (concat (substring s 0 beg) comp) comp)))
+      ('completion--unquote
+       (let ((qbeg 0) (qend nil))
+         (while (and (string-match crm-current-separator s qbeg)
+                     ;; P is Point here, not Predicate.
+                     (<= (match-end 0) p))
+           (setq qbeg (match-end 0)))
+         (setq qend (or (string-match crm-current-separator s qbeg)
+                        (length s)))
+         (seq-let (ustring utable upoint requote)
+             (complete-with-action a table (substring s qbeg qend) (- p qbeg))
+           (list ustring utable upoint
+                 (lambda (uresult op)
+                   (let ((result (funcall requote uresult op)))
+                     (pcase op
+                       (1 ;;try
+                        (if (stringp (car-safe result))
+                            (cons (concat (substring s 0 qbeg)
+                                          (car result)
+                                          (substring s qend))
+                                  (+ qbeg (cdr result)))
+                          result))
+                       (2 ;;all
+                        (when-let ((last (last result))
+                                   (base (or (cdr last) 0)))
+                          (setcdr last (+ base qbeg))
+                          result)))))))))
+      (_ (complete-with-action a table (substring s beg) p)))))
+
 ;;;###autoload
 (defun completing-read-multiple
   (prompt table &optional predicate require-match initial-input
@@ -370,27 +413,7 @@ with empty strings removed."
     (split-string
      (minibuffer-with-setup-hook
          #'completing-read-multiple-mode
-       (completing-read
-        prompt
-        (lambda (s p a)
-          (let ((beg 0))
-            (while (string-match crm-current-separator s beg)
-              (setq beg (match-end 0)))
-            (pcase a
-              (`(boundaries . ,suffix)
-               (let ((bounds (completion-boundaries
-                              (substring s beg) table p
-                              (substring suffix 0
-                                         (string-match crm-current-separator
-                                                       suffix)))))
-                 `(boundaries ,(+ (car bounds) beg) . ,(cdr bounds))))
-              ('metadata (completion-metadata (substring s beg) table p))
-              ('nil (let ((comp (complete-with-action a table
-                                                      (substring s beg) p)))
-                      (if (stringp comp)
-                          (concat (substring s 0 beg) comp)
-                        comp)))
-              (_ (complete-with-action a table (substring s beg) p)))))
+       (completing-read prompt (apply-partially #'crm--table table)
         predicate require-match initial-input hist def inherit-input-method))
      crm-current-separator t)))