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

From: Dmitry Gutov <[email-masked]>
Date: Tue, 28 Jan 2014 18:00:28 +0200

On 28.01.2014 15:24, Stefan Monnier wrote:
>> But should we document that the only way to retain the information about
>> different annotations corresponding to equal strings is to use text
>> properties?
>
> 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.

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.

Note that we're discussing both CAPF and company-backends interfaces 
here. And "different completions for equal strings" would be true for 
company-eclim, company-clang, probably company-semantic eventually, and 
also third-party packages: emacs-eclim (it bundles a different Company 
backend), and omnisharp-emacs.

We could consider it a bug, though (that annotation-function is called 
with different objects). Currently, the fact that `-all-completions' 
functions for different styles process the returned list with 
`completion-hilit-commonality' in undocumented. Maybe we should push 
that logic somewhere, or just document that -all-completions functions 
must process annotations themselves first? Though sorting, in 
`minibuffer-completion-help', would become more complicated and slower 
as a result.

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.

>> 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.

And actually, `completion-all-completions' already conveys some 
information to the front-end using text properties: it uses `face' to 
delimit the "common" parts of the completions using 
`completion-hilit-commonality'.

> I'd rather not
> force them to construct the annotation ahead of time "just in case it
> might get displayed".

But completion-at-point calls annotation-function on all completions 
anyway: in `minibuffer-completion-help'. After sorting, but before 
deleting duplicates. Or otherwise, how would it only delete duplicates 
only where both value and annotation are the same?

>     (mapcar (lambda (s)
>               (if (> (length s) 2)
>                   (let ((bound (/ (length s) 2))
>                         (comp (substring s 0 bound)))
>                     (put-text-property 0 bound 'annotation s comp)
>                     comp)
>                 s))
>             (all-completions "" obarray 'fboundp)))

Using `put-text-property' is a good point.

> Where the (substring s bound) is delayed to the annotation-function.
>
...
> That's also because you artificially moved a lot of processing to the
> all-completions step whereas some of that processing really belongs to
> the annotation step.

But that step gets performed for all candidates anyway (see above).
Using `value-function' instead of `annotation-function' would have 
changed that. Although yes, that interface would be less neat.

>> But wouldn't it clash with the current completion-at-point interface?
>
> I don't see why.  The `finished' case is exactly for things like "insert
> a terminator, record the user's choice somewhere, or some other thing
> which only makes sense when you somehow know this part of the completion
> is over".
>
>> I don't think we can define a CAPF function without regard to how it
>> work there.
>
> Can't see why not.

Yeah, okay.