* Completion Exit:: Completion and minibuffer text submission.
* Completion Styles:: How completion matches are chosen.
* Narrow Completions:: Restricting completion candidates.
+* Completion Multi:: Providing multiple inputs at once.
* Completion Options:: Options for completion.
Help
* Completion Exit:: Completion and minibuffer text submission.
* Completion Styles:: How completion matches are chosen.
* Narrow Completions:: Restricting completion candidates.
+* Completion Multi:: Providing multiple inputs at once.
* Completion Options:: Options for completion.
@end menu
@kindex C-x / @r{(completion)}
@findex minibuffer-set-completion-styles
- @kbd{C-x /} (minibuffer-set-completion-styles) lets you set the
-completion styles for the current minibuffer. @xref{Completion
+ @kbd{C-x /} (@code{minibuffer-set-completion-styles}) lets you set
+the completion styles for the current minibuffer. @xref{Completion
Styles}. This command prompts you for a list of completion styles,
and sets that list as the effective completion styles for following
completion operations in the current minibuffer. With a plain prefix
it removes all restrictions without prompting, regardless of how many
there are.
+@node Completion Multi
+@subsection Read and Complete Multiple Inputs
+
+@cindex multiple inputs, with completion
+ Some commands read @emph{multiple inputs} from the minibuffer at
+once. For example, @kbd{M-x describe-face} prompts you for @emph{one
+or more} face names, and displays a help buffer describing all given
+faces. @xref{Faces}. This works just like reading a single inputs,
+except that you can type several inputs in the minibuffer, separating
+them with @dfn{input separators}. You can use completion to fill in
+the individual inputs, as usual.
+
+@cindex input separators, for reading multiple inputs
+@cindex separator pattern, for reading multiple inputs
+ The input separator is typically a comma (@samp{,}), so if a command
+@kbd{M-x foo} reads multiple inputs, and you type @kbd{bar,baz,spam
+@key{RET}} in the minibuffer, then @code{foo} gets a list of three
+inputs: @samp{bar}, @samp{baz} and @samp{spam}. More generally, Emacs
+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
+mode line. You can hover over that indicator with the mouse to get
+help about the current input separator pattern.
+
+ The following commands are available in the minibuffer while reading
+multiple inputs:
+
+@kindex C-x ,
+@findex crm-change-separator
+ @kbd{C-x ,} (@code{crm-change-separator}) prompts you for a regular
+expression, and sets the current input separator pattern to that
+regular expression. Use this command if the default separator pattern
+is inconvenient or mistakes a part of your input to be a separator.
+With a prefix argument, that is if you type @kbd{C-u C-x ,}, this
+command also replaces all current input separators in the minibuffer
+with a new separator that you provide.
+
+@kindex C-,
+@findex crm-complete-and-insert-separator
+ @kbd{C-,} (@code{crm-complete-and-insert-separator}) completes
+partial inputs in the minibuffer, and then inserts a new input
+separator at the end of the minibuffer and puts point after it, for
+you to type another input. In order to insert a separator for you,
+this command must get a hold of a string that matches the current
+separator pattern. Some commands that read multiple inputs specify a
+so-called @dfn{canonical separator}, in which case @kbd{C-,} uses the
+canonical separator. Otherwise, this command tries to find an
+appropriate separator by looking at your current input, and applying
+some heuristics that work for common separator patterns. In case
+@code{C-,} cannot figure out which separator to insert by itself, it
+prompts you for a separator and remembers your choice as the canonical
+separator for the current minibuffer.
+
@node Completion Options
@subsection Completion Options
@code{completing-read-multiple} input separators. By default, this is
set to @samp{[ \t]*,[ \t]*}, which means that a comma, possibly
surrounded by spaces or tabs, separates
-@code{completing-read-multiple} inputs.
+@code{completing-read-multiple} inputs. You can also set this
+variable to a cons cell @code{(@var{regexp} . @var{canonical})}, where
+@var{regexp} is the regular expression for matching separators, and
+@var{canonical} is a ``canonical'' separator string that Emacs uses
+when it inserts a separator in behalf of the user. If @var{canonical}
+does not match @var{regexp}, @var{canonical} is ignored.
@end defvar
-@deffn Command crm-change-separator
-This command, bound to @kbd{C-x ,} in the minibuffer during
-@code{completing-read-multiple}, changes the current input separator.
-It prompts for a new separator regular expression, and sets the local
-value of @code{crm-separator} to that regular expression. With a
-prefix argument, this command also prompts for a replacement string
-(that should match the new separator) and replaces all of the existing
-separators in the minibuffer with that replacement string.
-@end deffn
-
-
@node Completion Commands
@subsection Minibuffer Commands that Do Completion
strings. 'completing-read-multiple' binds 'C-x ,' to
'crm-change-separator' in the minibuffer.
++++
+*** New command 'crm-complete-and-insert-separator'.
+This command, bound to 'C-,' in 'completing-read-multiple'
+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.
+
+++
*** New command 'minibuffer-set-completion-styles'.
This command, bound to 'C-x /' in the minibuffer, lets you set the
(defvar crm-separator "[ \t]*,[ \t]*"
"Separator regexp used for separating strings in `completing-read-multiple'.
-It should be a regexp that does not match the list of completion candidates.")
+It should be a regexp that does not match the list of completion candidates.
+
+This can also be a cons cell (REGEXP . CANONICAL), where REGEXP
+is the separator regexp used for matching input separators, and
+CANONICAL is a canonical separator string that Emacs uses when it
+inserts a separator for you. If CANONICAL does not match REGEXP,
+it is ignored. See also `crm-complete-and-insert-separator'.")
+
+(defvar crm-common-separators '(",")
+ "List of strings often used to separate multiple minibuffer inputs.
+
+See also `crm-complete-and-insert-separator'.")
(defvar crm-current-separator nil
"The value of `crm-separator' for the current minibuffer.")
+(defvar crm-canonical-separator nil
+ "Canonical separator for `completing-read-multiple'.
+
+This can either a string that matches `crm-current-separator', or
+nil when there is no canonical separator.")
+
(defun crm-complete-and-exit ()
"If all of the minibuffer elements are valid completions then exit.
All elements in the minibuffer must match. If there is a mismatch, move point
to the location of mismatch and do not exit.
This function is modeled after `minibuffer-complete-and-exit'."
- (interactive)
+ (interactive "" minibuffer-mode)
(let ((bob (minibuffer--completion-prompt-end))
(doexit t))
(goto-char bob)
(goto-char (minibuffer-prompt-end))
(while (re-search-forward crm-current-separator nil t)
(replace-match rep t t)))
- (setq crm-current-separator sep)
+ (setq crm-current-separator sep crm-canonical-separator rep)
(when (get-buffer-window "*Completions*" 0)
;; Update *Completions* to avoid stale `completion-base-affixes'.
(minibuffer-completion-help)))
+(defun crm-complete-and-insert-separator ()
+ "Complete partial inputs and then insert a new input separator.
+
+If `crm-canonical-separator' is non-nil and matches the regular
+expression `crm-current-separator', then this command uses
+`crm-canonical-separator' as the separator. Otherwise, this
+command tries to find an appropriate separator by matching
+`crm-current-separator' against your current input and against
+the list of common separators in `crm-common-separators', and if
+that fails this command prompts you for the separator to use."
+ (interactive "" minibuffer-mode)
+ (let ((bob (minibuffer--completion-prompt-end))
+ (all-complete t)
+ (enable-recursive-minibuffers t))
+ ;; Establish a canonical separator string, so we can insert it.
+ (setq crm-canonical-separator
+ (or
+ ;; If `crm-canonical-separator' matches, use it.
+ (and (stringp crm-canonical-separator)
+ (string-match-p crm-current-separator
+ crm-canonical-separator)
+ crm-canonical-separator)
+ ;; If there's some separator already, use that.
+ (and (save-excursion
+ (goto-char bob)
+ (re-search-forward crm-current-separator nil t))
+ (buffer-substring-no-properties (match-beginning 0)
+ (match-end 0)))
+ ;; If any common separator matches, use it.
+ (seq-some (lambda (sep)
+ (and (string-match-p crm-current-separator sep)
+ sep))
+ crm-common-separators)
+ ;; Ask the user for help.
+ (read-string-matching crm-current-separator
+ "Separate inputs with: ")))
+ (while
+ (and all-complete
+ (let* ((beg (save-excursion
+ (if (re-search-backward crm-current-separator bob t)
+ (match-end 0)
+ bob)))
+ (end (copy-marker
+ (save-excursion
+ (if (re-search-forward crm-current-separator nil t)
+ (match-beginning 0)
+ (point-max)))
+ t)))
+ (goto-char end)
+ (setq all-complete nil)
+ (completion-complete-and-exit
+ beg end (lambda () (setq all-complete t)))
+ (goto-char end)
+ (not (eobp)))
+ (looking-at crm-current-separator))
+ (when all-complete
+ (goto-char (match-end 0))))
+ (when all-complete
+ (if (looking-back crm-current-separator bob)
+ ;; Separator already present, show completion candidates.
+ (minibuffer-completion-help)
+ (insert crm-canonical-separator)))))
+
(define-minor-mode completions-multi-mode
"Minor mode for reading multiple strings in the minibuffer."
:lighter (:eval
- (propertize " Multi" 'help-echo
- (concat
- "Insert multiple inputs by separating them with \""
- (buffer-local-value 'crm-current-separator
- completion-reference-buffer)
- "\""))))
+ (let ((canonical
+ (buffer-local-value 'crm-canonical-separator
+ completion-reference-buffer)))
+ (propertize
+ (concat
+ " Multi"
+ (when canonical (concat "[" crm-canonical-separator "]")))
+ 'help-echo
+ (concat
+ "Insert multiple inputs by separating them with \""
+ (or canonical
+ (buffer-local-value 'crm-current-separator
+ completion-reference-buffer))
+ "\"")))))
(defun crm-completion-setup ()
"Enable `completions-multi-mode' in *Completions* buffer."
(defvar-keymap completing-read-multiple-mode-map
:doc "Keymap for `completing-read-multiple-mode'."
"<remap> <minibuffer-complete-and-exit>" #'crm-complete-and-exit
- "C-x ," #'crm-change-separator)
+ "C-x ," #'crm-change-separator
+ "C-," #'crm-complete-and-insert-separator)
(define-minor-mode completing-read-multiple-mode
"Minor mode for reading multiple strings in the minibuffer."
This function returns a list of the strings that were read,
with empty strings removed."
- (let ((crm-current-separator crm-separator))
+ (let ((crm-current-separator
+ (if (consp crm-separator)
+ (car crm-separator)
+ crm-separator))
+ (crm-canonical-separator (cdr-safe crm-separator)))
(split-string
(minibuffer-with-setup-hook
#'completing-read-multiple-mode