Subject: bug#16555: 24.3.50; Company and CAPF: dealing with completion values containing extra text

From: Stefan Monnier <[email-masked]>
Date: Tue, 28 Jan 2014 17:04:39 -0500

>> We could add a note somewhere, I guess.  So far, "different completions
>> for equal strings" is a very rare situation.
> Not "different completions", but rather different displayed information and
> exit behavior.

Yes, that's what I meant by "different completions with equal strings".

> AFAICS, using annotation-function is a very rare situation by itself (in
> Emacs core, only `lisp-completion-at-point' does). I blame the bare-bones
> completion interface.

No need to blame anyone/anything.  CAPF needs to improve the annotation
support, indeed.  I don't think the current annotation-function is
sufficient, since there are different kinds of annotations.  E.g. adding
"<f>" is not the same as adding "(int x, float y, Vector<String>)" for
simple reasons of screen real estate, so in some UIs you'd want to
display both, while in others you'd only want the short one.

> We could consider it a bug, though (that annotation-function is called with
> different objects).

Not really: the "objects" you're talking about are returned by the
completion-table, i.e. they cover at most one "field" (in the
completion-boundaries sense), whereas completion-all-completions returns
strings that can span several fields, so clearly they can't always be
`eq' to something returned by the completion-table.

> Currently, the fact that `-all-completions' functions for different
> styles process the returned list with completion-hilit-commonality' in
> undocumented.

Indeed, but it's only part of the reason for the problem you see.
And there's no way to do the highlighting elsewhere: only the style
knows how to relate the input string (and point's position within in) to
the various output candidates.

> Maybe we should push that logic somewhere, or just document
> that -all-completions functions must process annotations
> themselves first?

The idea is rather to let the backend provide more kinds of annotations
and let the UI choose which one to use.  E.g. icomplete-mode doesn't
want any annotation at all, because its screen real-estate is
very limited.  So completion-all-completions can't blindly add annotations.

> Though sorting, in minibuffer-completion-help', would become more
> complicated and slower as a result.

I don't see how that's related.

> Come to think of it, company-backends should be able to use a hash-table
> with `eq' test maybe already, or if I massage the code a little. The major
> question for me was about uniqueness, and looks like, yes, doing
> delete-consecutive-dups' after fetching all annotations should be fast
> enough (and this approach even has some space for optimization). So that
> leaves a problem with CAPF.

That sounded like "thinking out loud for myself".  I don't know what you
wanted to say nor how that relates to CAPF.  FWIW,
minibuffer-completion-help uses `sort' on the "annotated completions"
and then display-completion-list uses delete-consecutive-dups (tho hand
written into the loop).

>>> And if text properties is the only way, maybe dispense with the annotation
>>> function and just document the desired property on the strings?
>> None of the annotation functions so far use text-properties, because the
>> completion candidate strings are all different anyway.
> It could be an either/or specification: if annotation-function is defined,
> use it, otherwise, look up the `annotation' property.

I think that in most cases the annotation function will want to do some
work rather than just return the content of the annotation (as in the
sample code in my previous message).

> But completion-at-point calls annotation-function on all completions anyway:

minibuffer-completion-help does.  completion-at-point also does when it
delegates to minibuffer-completion-help.  But minibuffer-force-complete
doesn't.  And neither does icomplete.

> After sorting, but before deleting duplicates.

Indeed.

> But that step gets performed for all candidates anyway (see above).

As shown above, no, not always.

        Stefan