Subject: Re: bug#14061: 24.3.50; Globbing in completion not working correctly

From: Michael Heerdegen <[email-masked]>
Date: Wed, 27 Mar 2013 03:49:38 +0100

Michael Heerdegen <[email-masked]> writes:

> >    C-h v *compil*warn* TAB TAB
> >
> > "byte-compile-warnings" should be among the matches, but that's not
> > the case.
>
> Looks like `completion-pcm--merge-completions' is introducing the error:
>
> (completion-pcm--merge-completions
>  '("byte-compile-error-on-warn"
>    "byte-compile-warning-types"
>    "byte-compile-warnings"
>    "byte-compile-last-warned-form")
>  '(star "compil" star "warn"))
>
> ==>
>
> (any "warn" "-" star "compile-" "byte-")

Some more thoughts:

In the definition of `completion-pcm--merge-completions', we have

  (when (memq elem '(star point prefix))
    ;; Extract common suffix additionally to common prefix.
    ;; Only do it for `point', `star', and `prefix' since for
    ;; `any' it could lead to a merged completion that
    ;; doesn't itself match the candidates.
    (let ((suffix (completion--common-suffix comps)))
      (cl-assert (stringp suffix))
      (unless (equal suffix "")
        (push suffix res))))

In the pathological cases, the `suffix' includes a hyphen that is
already included in the prefix:

  (completion-pcm--merge-completions
   '("byte-compile-error-on-warn"
     "byte-compile-warning-types"
     "byte-compile-warnings"
     "byte-compile-last-warned-form")
   '(star "compil" star "warn"))       ;; suffix == "-"

  (completion-pcm--merge-completions
   '("byte-compile-a-warning-types"
     "byte-compile-a-test-warning-types")
   '(star "compile" star "types"))     ;; suffix == "-warning-"

but not all cases where `suffix' starts with "-" are problematic:

  (completion-pcm--merge-completions
   '("byte-compile-a-c-b-warning-types"
     "byte-compile-a-test-b-warning-types")
   '(star "compile" star "types"))

so it would be wrong to remove a leading "-" from `suffix'
unconditionally.

Dunno what a good fix would look like.  It tried

  (let* ((pre-length (length prefix))
         (suffix (completion--common-suffix
                  (mapcar (lambda (comp) (substring comp pre-length))
                          comps))))
    (cl-assert (stringp suffix))
    (unless (equal suffix "")
      (push suffix res)))

which seems to work, but my insight in this code is limited.

HTH,

Michael.