Subject: bug#74420: 31.0.50; PCM completion for ~/src/emacs/trunk/*/minibuf breaks

From: Spencer Baugh <[email-masked]>
Date: Wed, 27 Nov 2024 14:30:36 -0500

Spencer Baugh <[email-masked]> writes:
> Stefan Monnier <[email-masked]> writes:
>>> Actually... I just realized this misses some cases, namely when we have
>>> "star point" or "point star".
>>
>> FWIW, my local patches have included for years optimizations like the
>> ones you suggested *and* they replaced `star point` and `point star`
>> with just `star`.
>>
>> Do you think it's important to preserve `point` in those cases?
>
> Hm, I'm not sure.  I've been playing around with alternative ways to
> move point in pcm-try-completion but haven't yet got something I'm
> satisfied with.  So let me defer this question until I've hacked on that
> some more :)

Okay, so I ended up not wanting to move point.

What I have instead now is something which explicitly inserts a * in the
minibuffer, specifically with completion-pcm-leading-wildcard:

diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
index 01502235403..db13c659004 100644
--- a/lisp/minibuffer.el
+++ b/lisp/minibuffer.el
@@ -3925,7 +3925,7 @@ completion-pcm--string->pattern
               (setq p0 p)
             (push (substring string p (match-end 0)) pattern)
             ;; `any-delim' is used so that "a-b" also finds "array->beginning".
-            (setq pending 'any-delim)
+            (setq pending (if completion-pcm-leading-wildcard 'star 'any-delim))
             (setq p0 (match-end 0))))
         (setq p p0))
 
@@ -3935,7 +3935,7 @@ completion-pcm--string->pattern
       (setq pattern (nreverse pattern))
       (when completion-pcm-leading-wildcard
         (when (stringp (car pattern))
-          (push 'prefix pattern)))
+          (push 'star pattern)))
       pattern)))
 
 (defun completion-pcm--optimize-pattern (p)
-- 
2.39.3

This does two things:

- completion-pcm-leading-wildcard previously had inconsistent behavior:
  if completion-pcm--find-all-completions makes a recursive call,
  completion-pcm-leading-wildcard would effectively add a leading
  wildcard to each component.  But that wouldn't happen if the original
  pattern happens to match, in the first completion-pcm--all-completions
  call.  To make them behave identically, now
  completion-pcm-leading-wildcard changes the 'any-delim inserted at the
  start of each component into a proper wildcard.  This is just a
  bugfix.

- More radically, actually insert a * in the minibuffer text if we run
  completion-pcm-try-completion with completion-pcm-leading-wildcard=t.

Inserting a * is pretty nice for multiple reasons.

Paradoxically, inserting a * makes things more efficient for the
configuration I intend people to use, where completion-styles contains:

... partial-completion (partial-completion ((completion-pcm-leading-wildcard t))) ...

With this configuration, if partial-completion fails, we make one call
to the expensive completion-pcm-leading-wildcard=t mode, and then
afterwards the explicit *s cause us to stay in regular
partial-completion, with only the exact amount of leading wildcards that
we actually need, rather than having an extra 'prefix wildcard at the
start of every single component.

And, inserting the * ensures that we stay in this "leading wildcard"
mode.  I've found that tab-completing with
completion-pcm-leading-wildcard tends to sometimes change the minibuffer
contents such that subsequent tab-completions get handled by another
completion style.  With leading wildcards, that's pretty undesirable,
because it can make the set of completions much narrower.  But
explicitly inserting the * forces the leading-wildcard behavior to stay
around.

And it just looks pretty good: because the 'star wildcards are removed
if they can't expand to anything, when you hit TAB the * are basically
inserted everywhere that you might add new text.  This is pretty neat.

I usually use completion-pcm-leading-wildcard with project-find-file,
so e.g. this is a decent way to test:

(setf (alist-get 'project-file completion-category-overrides)
      '((styles basic partial-completion (partial-completion ((completion-pcm-leading-wildcard t))))))

Then C-x p f in the Emacs repo

What do you think?