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-2款新车/将推电动车
1 Answer
: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 withcomplete()
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.
-
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 withcomplete()
but it does not seems trivial. It may be also worth mentioning thatpopup_at_cursor
may be also used to achieve similar functionalities. No? Commented Feb 14 at 10:40 -
See my edit. I don't know about
:help popup_at_cursor()
. Never used it.– romainlCommented Feb 14 at 12:51