mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-06-14 12:31:25 +00:00
New command 'crm-complete-and-insert-separator'
* lisp/emacs-lisp/crm.el (crm-complete-and-insert-separator): New command. (completing-read-multiple-mode-map): Bind it to 'C-,'. (crm-canonical-separator, crm-common-separators): New variables. (completions-multi-mode): Adapt mode line lighter. (crm-complete-and-exit): Only suggest in 'M-x' in 'minibuffer-mode'. (crm-change-separator): (Re)set canonical separator. * doc/lispref/minibuf.texi (Minibuffer Completion): Update. * doc/emacs/mini.texi (Completion Multi): New subsection. (Completion Commands): Fix markup. (Completion) * doc/emacs/emacs.texi (Top): Add menu entry. * etc/NEWS: Announce 'crm-complete-and-insert-separator'.
This commit is contained in:
parent
1ab31ae0e5
commit
dc4ce1052b
5 changed files with 177 additions and 25 deletions
|
|
@ -295,6 +295,7 @@ Completion
|
|||
* 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
|
||||
|
|
|
|||
|
|
@ -293,6 +293,7 @@ Completion}.
|
|||
* 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
|
||||
|
||||
|
|
@ -489,8 +490,8 @@ there are.
|
|||
|
||||
@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
|
||||
|
|
@ -822,6 +823,62 @@ If you invoke this command with a prefix argument (@kbd{C-u C-x n w}),
|
|||
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
|
||||
|
||||
|
|
|
|||
|
|
@ -1270,20 +1270,14 @@ The value of this variable is a regular expression that matches
|
|||
@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
|
||||
|
||||
|
|
|
|||
7
etc/NEWS
7
etc/NEWS
|
|
@ -821,6 +821,13 @@ This command lets you change the separator that
|
|||
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
|
||||
|
|
|
|||
|
|
@ -85,18 +85,35 @@
|
|||
|
||||
(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)
|
||||
|
|
@ -177,20 +194,91 @@ for REP as well."
|
|||
(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."
|
||||
|
|
@ -205,7 +293,8 @@ for REP as well."
|
|||
(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."
|
||||
|
|
@ -235,7 +324,11 @@ contents of the minibuffer are \"alice,bob,eve\" and point is between
|
|||
|
||||
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
|
||||
|
|
|
|||
Loading…
Reference in a new issue