]> git.eshelyaron.com Git - emacs.git/commitdiff
Highlight input separators in 'c-r-m' minibuffers
authorEshel Yaron <me@eshelyaron.com>
Sat, 20 Jan 2024 19:03:20 +0000 (20:03 +0100)
committerEshel Yaron <me@eshelyaron.com>
Sat, 20 Jan 2024 19:09:12 +0000 (20:09 +0100)
* lisp/emacs-lisp/crm.el (crm-separator): New face.
(crm-highlight-separators): New function.
(crm-change-separator, completing-read-multiple-mode): Use it.

* doc/emacs/mini.texi (Completion Multi): Mention sep highlighting.

* etc/NEWS: Announce it.

doc/emacs/mini.texi
etc/NEWS
lisp/emacs-lisp/crm.el

index b6744776fd2b06d07851687c32213656df6be3c6..ca5f6d0dc0b8a2bc15a4dfd824795bf30f17598b 100644 (file)
@@ -848,8 +848,12 @@ treats a part of your minibuffer input as an input separator when it
 matches the current @dfn{separator pattern}---a regular expression
 that may change from command to command.  The default separator
 pattern, which most commands use, matches a comma along with any
-surrounding spaces or tabs.  When reading multiple inputs, the
-@file{*Completions*} buffer displays the @samp{Multi} indicator in the
+surrounding spaces or tabs.
+
+@noindent
+When reading multiple inputs, Emacs highlights input separators in the
+minibuffer with the @code{crm-separator} face, and the
+@file{*Completions*} buffer displays the indicator @samp{Multi} in the
 mode line.  You can hover over that indicator with the mouse to get
 help about the current input separator pattern.
 
index 013d76eb44ba462df9e918b79f83214982021929..ac743cd0bf10fee5c291a0ac78a2e903ebfffeee 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -792,6 +792,12 @@ minibuffers, completes partial inputs that are already in the
 minibuffer, and inserts a new separator at the end of the minibuffer
 for you to insert a another input.
 
++++
+*** Highlight 'completing-read-multiple' separators in the minibuffer.
+Emacs now highlights input separators when you provide multiple inputs
+in the minibuffer for 'completing-read-multiple'.  This highlighting
+uses the new 'crm-separator' face.
+
 +++
 *** 'completion-category-overrides' supports more metadata.
 The new supported completion properties are 'cycle-sort-function',
index ebea8b060e16e73a2a7133cb2bcdb2d371aa33f6..32221047c20ce43f0784db2987ed84dcfaa81880 100644 (file)
@@ -191,11 +191,13 @@ for REP as well."
            (when current-prefix-arg
              (read-string-matching sep "Replace existing separators with: "))))
    minibuffer-mode)
-  (when rep
-    (goto-char (minibuffer-prompt-end))
-    (while (re-search-forward crm-current-separator nil t)
-      (replace-match rep t t)))
+  (save-excursion
+    (when rep
+      (goto-char (minibuffer-prompt-end))
+      (while (re-search-forward crm-current-separator nil t)
+        (replace-match rep t t))))
   (setq crm-current-separator sep crm-canonical-separator rep)
+  (crm-highlight-separators (minibuffer-prompt-end) (point-max))
   (when (get-buffer-window "*Completions*" 0)
     ;; Update *Completions* to avoid stale `completion-base-affixes'.
     (minibuffer-completion-help)))
@@ -291,6 +293,34 @@ that fails this command prompts you for the separator to use."
 (define-obsolete-variable-alias 'crm-local-must-match-map
   'completing-read-multiple-mode-map "30.1")
 
+(defface crm-separator
+  '((t :inherit minibuffer-prompt))
+  "Face for highlighting input separators in multi-input minibuffers."
+  :version "30.1")
+
+(defun crm-highlight-separators (beg end &optional _)
+  "Highlight current minibuffer input separators between BEG and END."
+  (let* ((bob (minibuffer-prompt-end))
+         (beg (or (save-excursion
+                    (goto-char beg)
+                    (re-search-backward crm-current-separator bob t))
+                  bob))
+         (end (or (save-excursion
+                    (goto-char end)
+                    (re-search-forward crm-current-separator nil t))
+                  (point-max)))
+         (ovs (seq-filter (lambda (ov) (overlay-get ov 'crm-separator))
+                          (overlays-in beg end))))
+    (mapc #'delete-overlay ovs)
+    (save-excursion
+      (goto-char beg)
+      (save-match-data
+        (while (re-search-forward crm-current-separator nil t)
+          (let ((ov (make-overlay (match-beginning 0) (match-end 0))))
+            (overlay-put ov 'face 'crm-separator)
+            (overlay-put ov 'crm-separator t)
+            (overlay-put ov 'evaporate t)))))))
+
 (defvar-keymap completing-read-multiple-mode-map
   :doc "Keymap for `completing-read-multiple-mode'."
   "<remap> <minibuffer-complete-and-exit>" #'crm-complete-and-exit
@@ -299,10 +329,17 @@ that fails this command prompts you for the separator to use."
 
 (define-minor-mode completing-read-multiple-mode
   "Minor mode for reading multiple strings in the minibuffer."
-  :lighter nil
+  :interactive nil
   (if completing-read-multiple-mode
-      (add-hook 'completion-setup-hook #'crm-completion-setup 10 t)
-    (remove-hook 'completion-setup-hook #'crm-completion-setup t)))
+      (progn
+        (add-hook 'completion-setup-hook #'crm-completion-setup 10 t)
+        (add-hook 'after-change-functions #'crm-highlight-separators nil t)
+        (crm-highlight-separators (minibuffer-prompt-end) (point-max)))
+    (remove-hook 'completion-setup-hook #'crm-completion-setup t)
+    (remove-hook 'after-change-functions #'crm-highlight-separators t)
+    (mapc #'delete-overlay
+          (seq-filter (lambda (ov) (overlay-get ov 'crm-separator))
+                      (overlays-in (minibuffer-prompt-end) (point-max))))))
 
 ;;;###autoload
 (defun completing-read-multiple