0

I am in need of making my own complete function and I found two ways for doing that: complete() and &completefunc. However, I cannot distinguish the different use-cases they are designed for.

1 Answer 1

0

:help 'completefunc' lets you define a function that will be used when you press <C-x><C-u> in insert mode, while :help complete() is a more low-level function that can be used in any arbitrary insert mode mapping.

If I planned to offer a single custom insert mode completion that is functionally different from the existing ones to my users, then I would use the former as it is, I think, more canonical.

If I planned to offer a range of custom insert mode completions, possibly overlapping with existing ones, then I would create all the necessary insert mode mappings and related custom functions, which would all use the latter under the hood.

:help complete-items applies to both.

Note that the two-stages mechanism described under :help 'completefunc' is more complicated than the one described under :help complete() but that is only due to the different abstraction levels at which they operate:

  • &completfunc handles everything from grabbing the stub to returning the list of completions,
  • complete() only triggers the completion mechanism with the given list of completion.

In reality, the shape of the value you would return from &completefunc and that of the one you would pass to complete() would fundamentally be the same. The potentially complicated stuff happens before return for the former and before calling complete() for the latter.

One thing that it is worth mentioning, is that complete() it shows a list and then you should avoid inserting anything, whereas 'completefunc' allows you to keep in inserting text and the displayed list is filtered as you type. Perhaps it is possible to achieve the same with complete() but it does not seems trivial.

That is the difference in abstraction levels I mentioned earlier. &completefunc allows you to hook your logic into the existing completion mechanism while complete() is a lower-level tool that must be used in combination with other tools for a good user experience. In concrete terms, a (extremely simplified) &completefunc would look something like this:

function! MyCompleteFunc(a, b)
    let myCompletionList = <complicated logic>
    return myCompletionList
endfunction

while completefunc() would be used like this:

function! MyCustomCompletion()
    let myCursorPosition = <complicated logic>
    let myCompletionList = <complicated logic>
    call complete(myCursorPosition, myCompletionList)
endfunction

with MyCustomCompletion() being part of a larger system that is yours to write as per your requirements, with mappings, autocommands and so on.

So it's a trade-off:

  • With &completefunc, the UX is done for you and you only have to write the code that generates/updates the completion list but you can only use <C-x><C-u>.

  • With complete(), you are not restricted to <C-x><C-u> but you have to handle everything by yourself, including triggering completion, generating/updating the list, etc.

Which circles back to the two use cases at the top of this answer.

2
  • One thing that it is worth mentioning, is that complete() it shows a list and then you should avoid inserting anything, whereas 'completefunc' allows you to keep in inserting text and the displayed list is filtered as you type. Perhaps it is possible to achieve the same with complete() but it does not seems trivial. It may be also worth mentioning that popup_at_cursor may be also used to achieve similar functionalities. No?
    – Barzi2001
    Commented Feb 14 at 10:40
  • See my edit. I don't know about :help popup_at_cursor(). Never used it.
    – romainl
    Commented Feb 14 at 12:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.