Subject: Re: bug#77718: 31.0.50; completion styles substring and flex are broken

From: Stefan Monnier <[email-masked]>
Date: Wed, 18 Jun 2025 16:10:11 -0400

> diff --git a/lisp/minibuffer.el b/lisp/minibuffer.el
> index 122459be062..598383e7b51 100644
> --- a/lisp/minibuffer.el
> +++ b/lisp/minibuffer.el
> @@ -4516,6 +4516,14 @@ completion--common-suffix
>    "Return the common suffix of the strings STRS."
>    (nreverse (try-completion "" (mapcar #'reverse strs))))
>  
> +(defcustom completion-/-not-common-suffix nil
> +  "If non-nil, ignore \"/\" as common suffix.
> +With the substring completion style enabled, this prevents displaying
> +\"/\" as the common substring suffix when all completion candidate end
> +in \"/\" (that was the only dispay prior to Emacs 31)."
> +  :version "31.1"
> +  :type 'boolean)

Like Daniel, I'd much rather find a solution that doesn't involve
a user config.

>  (defun completion-pcm--merge-completions (strs pattern)
>    "Extract the commonality in STRS, with the help of PATTERN.
>  PATTERN can contain strings and symbols chosen among `star', `any', `point',
> @@ -4622,7 +4630,9 @@ completion-pcm--merge-completions
>                                  (mapcar (lambda (str) (substring str skip))
>                                          comps))))))
>                        (cl-assert (stringp suffix))
> -                      (unless (equal suffix "")
> +                      (unless (if completion-/-not-common-suffix
> +                                  (member suffix '("" "/"))
> +                                (equal suffix ""))
>                          (push suffix res))))
>                    ;; We pushed these wildcards on RES, so we're done with them.
>                    (setq wildcards nil))

Comments:

- We shouldn't hardcode "/" here, since this code is not specific to
  file names.  IOW we should use the `completion-boundaries`
  functionality instead to detect if the suffix is equal to the
  boundary separator.
- Maybe we can/should limit this "/" special case to the situation where
  `prefix` is empty (or where the string before "suffix" also ends in
  a boundary-separator).

        Stefan