Subject: bug#47711: bug#48841: bug#47711: bug#48841: bug#47711: [PATCH VERSION 2] Add new `completion-filter-completions` API and deferred highlighting

From: Stefan Monnier <[email-masked]>
Date: Wed, 25 Oct 2023 16:50:29 -0400

This sounds fairly reasonable: the worst-case breakage seems to be that
we may occasionally lose highlighting because the var was non-nil at the
wrong time.

Sidenote: since the hash-table uses `eq` we don't need to use `gensym`,
we can use something like `cons` instead, which is cheaper and doesn't
risk making its way into the `obarray`.

> +(defun completion-lazy-hilit (str)
> +  "Return a copy of completion STR that is `face'-propertized.
> +See documentation for variable `completion-lazy-hilit' for more
> +details."
> +  (completion--hilit-from-re
> +   (copy-sequence str)
> +   (gethash completion-lazy-hilit completion--lazy-hilit-table)))

Hmm... in order to get the right result you need to call
`completion-lazy-hilit` sometime after calling
`completion-all-completions` and before the next call to
`completion-all-completions` done with the same value of
`completion-lazy-hilit`, right?

So how important is it to use a hash-table rather than a variable
holding just "the info about the last call to
`completion-all-completions`"?

> +           last-md
> +           (score (lambda (str)
> +                    (unless (string-match re str)
> +                      (error "Internal error: %s does not match %s" re str))
> +                    (let* ((match-end (match-end 0))
> +                           (md (cddr (setq last-md (match-data t last-md)))))
> +                      (completion--flex-score-1 md match-end (length str))))))
> +      (cond (completion-lazy-hilit
> +             (puthash completion-lazy-hilit re completion--lazy-hilit-table)
> +             (mapc (lambda (str)
> +                     (put-text-property 0 1 'completion-score (funcall score str) str))
> +                   completions))
> +            (t
> +             (mapcar
> +              (lambda (str)
> +                (setq str (copy-sequence str))
> +                (put-text-property 0 1 'completion-score (funcall score str) str)
> +                (completion--hilit-from-re str re)
> +                str)
> +              completions)))))

How much more expensive is it to replace the 

    (mapc (lambda (str)
            (put-text-property 0 1 'completion-score (funcall score str) str))
          completions))

with something like

    (let ((tail `(completion-lazy-hilit (completion--hilit-from-re ,re))))
      (mapc (lambda (str)
              (add-text-properties
               0 1 `(completion-score ,(funcall score str) ,@tail) str))
            completions))

and then get rid of the hash-table altogether?

        Stefan