Allow customizing partial-completion to be more like substring

The substring completion style completes "foo-bar" as "*foo-bar*".  The
partial-completion completion style completes "foo-bar" as "foo*bar*".

Previously, it was not possible to get completion of "foo-bar" to act as
"*foo*bar*", e.g. combining the partial-completion and substring styles.
This would be especially useful for things like project-find-file.

Now it is possible by customizing the completion-pcm-leading-wildcard variable
to a non-nil value.

Furthermore, it's convenient to be able to run
regular (completion-pcm-leading-wildcard=t, non-substring)
partial-completion before running completion-pcm-leading-wildcard=nil
partial-completion, since the former provides more narrowly targeted
completions.

It's possible to do this by customizing completion-styles.  Just add
'(partial-completion ((completion-pcm-leading-wildcard t))) and
'(partial-completion ((completion-pcm-leading-wildcard nil))) in that
order.  Then the completion machinery will first run partial-completion
with completion-pcm-leading-wildcard=t, and if that returns no
completions, run partial-completion with
completion-pcm-leading-wildcard=nil.

* lisp/minibuffer.el (completion--nth-completion): Allow an element of
completion-styles to contain a list of bindings.
(completion-styles): Document that.
(completion-pcm-leading-wildcard): Add.
(completion-pcm--string->pattern): Check completion-pcm-leading-wildcard.
(bug#70217)
This commit is contained in:
Spencer Baugh 2024-08-21 11:59:42 -04:00 committed by Eli Zaretskii
parent a7a22e7c22
commit 69ec333eab
3 changed files with 77 additions and 9 deletions

View file

@ -543,8 +543,14 @@ falls back on the next style.
@vindex completion-styles
The list variable @code{completion-styles} specifies the completion
styles to use. Each list element is the name of a completion style (a
Lisp symbol). The available style symbols are stored in the variable
styles to use. Each list element is either the name of a completion
style (a Lisp symbol) or a list starting with the name of a completion
style followed by @code{let}-style list of bindings which will be in
effect for that completion style. Multiple elements of
@code{completion-styles} can name the same completion style with
different variable bindings.
The available style symbols are stored in the variable
@code{completion-styles-alist} (@pxref{Completion Variables,,, elisp,
The Emacs Lisp Reference Manual}). The default completion styles are
(in order):
@ -569,6 +575,12 @@ Furthermore, a @samp{*} in the minibuffer text is treated as a
@dfn{wildcard}---it matches any string of characters at the
corresponding position in the completion alternative.
@vindex completion-pcm-leading-wildcard
If @code{completion-pcm-leading-wildcard} is set to @code{t}, this style
always acts as if a @dfn{wildcard} is present at the start of the
minibuffer text, similar to the @code{substring} style. For example,
@samp{l-m} will complete to @samp{emacs-lisp-mode}.
@item emacs22
@cindex @code{emacs22}, completion style
This completion style is similar to @code{basic}, except that it

View file

@ -43,6 +43,28 @@ The 'find-function', 'find-library', 'find-face-definition', and
'find-variable' commands now allow retrieving previous input using the
usual minibuffer history commands. Each command has a separate history.
** Minibuffer and Completions
+++
*** New user option 'completion-pcm-leading-wildcard'.
This option configures how the partial-completion style does completion.
It defaults to nil, which preserves the existing behavior. When it is set
to t, the partial-completion style behaves more like the substring
style, in that a string being completed can match against a candidate
anywhere in the candidate string.
+++
*** 'completion-styles' now can contain lists of bindings.
In addition to being a symbol naming a completion style, an element of
'completion-styles' can now be a list of the form '(STYLE ((VARIABLE
VALUE) ...))' where STYLE is a symbol naming a completion style.
VARIABLE will be bound to VALUE (without evaluating it) while the style
is executing. This allows multiple references to the same style with
different values for completion-affecting variables like
'completion-pcm-leading-wildcard or 'completion-ignore-case'. This also
applies for the styles configuration in 'completion-category-overrides'
and 'completion-category-defaults'.
** Windows

View file

@ -1141,7 +1141,15 @@ and DOC describes the way this style of completion works.")
;; and simply add "bar" to the end of the result.
emacs22)
"List of completion styles to use.
The available styles are listed in `completion-styles-alist'.
An element should be a symbol which is listed in
`completion-styles-alist'.
An element can also be a list of the form
(STYLE ((VARIABLE VALUE) ...))
STYLE must be a symbol listed in `completion-styles-alist', followed by
a `let'-style list of variable/value pairs. VARIABLE will be bound to
VALUE (without evaluating it) while the style is handling completion.
This allows repeating the same style with different configurations.
Note that `completion-category-overrides' may override these
styles for specific categories, such as files, buffers, etc."
@ -1284,11 +1292,18 @@ overrides the default specified in `completion-category-defaults'."
(result-and-style
(seq-some
(lambda (style)
(let ((probe (funcall
(or (nth n (assq style completion-styles-alist))
(error "Invalid completion style %s" style))
string table pred point)))
(and probe (cons probe style))))
(let (symbols values)
(when (consp style)
(dolist (binding (cadr style))
(push (car binding) symbols)
(push (cadr binding) values))
(setq style (car style)))
(cl-progv symbols values
(let ((probe (funcall
(or (nth n (assq style completion-styles-alist))
(error "Invalid completion style %s" style))
string table pred point)))
(and probe (cons probe style))))))
(completion--styles md)))
(adjust-fn (get (cdr result-and-style) 'completion--adjust-metadata)))
(when (and adjust-fn metadata)
@ -3868,6 +3883,21 @@ the commands start with a \"-\" or a SPC."
(setq trivial nil)))
trivial)))
(defcustom completion-pcm-leading-wildcard nil
"If non-nil, partial-completion completes as if there's a leading wildcard.
If nil (the default), partial-completion requires a matching completion
alternative to have the same beginning as the first \"word\" in the
minibuffer text, where \"word\" is determined by
`completion-pcm-word-delimiters'.
If non-nil, partial-completion allows any string of characters to occur
at the beginning of a completion alternative, as if a wildcard such as
\"*\" was present at the beginning of the minibuffer text. This makes
partial-completion behave more like the substring completion style."
:version "30.1"
:type 'boolean)
(defun completion-pcm--string->pattern (string &optional point)
"Split STRING into a pattern.
A pattern is a list where each element is either a string
@ -3918,7 +3948,11 @@ or a symbol, see `completion-pcm--merge-completions'."
(when (> (length string) p0)
(if pending (push pending pattern))
(push (substring string p0) pattern))
(nreverse pattern))))
(setq pattern (nreverse pattern))
(when completion-pcm-leading-wildcard
(when (stringp (car pattern))
(push 'prefix pattern)))
pattern)))
(defun completion-pcm--optimize-pattern (p)
;; Remove empty strings in a separate phase since otherwise a ""