mirror of
https://github.com/neovim/neovim
synced 2025-07-16 01:01:49 +00:00
vim-patch:9.1.1301: completion: cannot configure completion functions with 'complete'
Problem: completion: cannot configure completion functions with
'complete'
Solution: add support for setting completion functions using the f and o
flag for 'complete' (Girish Palya)
This change adds two new values to the `'complete'` (`'cpt'`) option:
- `f` – invokes the function specified by the `'completefunc'` option
- `f{func}` – invokes a specific function `{func}` (can be a string or `Funcref`)
These new flags extend keyword completion behavior (e.g., via `<C-N>` /
`<C-P>`) by allowing function-based sources to participate in standard keyword
completion.
**Key behaviors:**
- Multiple `f{func}` values can be specified, and all will be called in order.
- Functions should follow the interface defined in `:help complete-functions`.
- When using `f{func}`, escaping is required for spaces (with `\`) and commas
(with `\\`) in `Funcref` names.
- If a function sets `'refresh'` to `'always'`, it will be re-invoked on every
change to the input text. Otherwise, Vim will attempt to reuse and filter
existing matches as the input changes, which matches the default behavior of
other completion sources.
- Matches are inserted at the keyword boundary for consistency with other completion methods.
- If finding matches is time-consuming, `complete_check()` can be used to
maintain responsiveness.
- Completion matches are gathered in the sequence defined by the `'cpt'`
option, preserving source priority.
This feature increases flexibility of standard completion mechanism and may
reduce the need for external completion plugins for many users.
**Examples:**
Complete matches from [LSP](https://github.com/yegappan/lsp) client. Notice the use of `refresh: always` and `function()`.
```vim
set cpt+=ffunction("g:LspCompletor"\\,\ [5]). # maxitems = 5
def! g:LspCompletor(maxitems: number, findstart: number, base: string): any
if findstart == 1
return g:LspOmniFunc(findstart, base)
endif
return {words: g:LspOmniFunc(findstart, base)->slice(0, maxitems), refresh: 'always'}
enddef
autocmd VimEnter * g:LspOptionsSet({ autoComplete: false, omniComplete: true })
```
Complete matches from `:iabbrev`.
```vim
set cpt+=fAbbrevCompletor
def! g:AbbrevCompletor(findstart: number, base: string): any
if findstart > 0
var prefix = getline('.')->strpart(0, col('.') - 1)->matchstr('\S\+$')
if prefix->empty()
return -2
endif
return col('.') - prefix->len() - 1
endif
var lines = execute('ia', 'silent!')
if lines =~? gettext('No abbreviation found')
return v:none # Suppresses warning message
endif
var items = []
for line in lines->split("\n")
var m = line->matchlist('\v^i\s+\zs(\S+)\s+(.*)$')
if m->len() > 2 && m[1]->stridx(base) == 0
items->add({ word: m[1], info: m[2], dup: 1 })
endif
endfor
return items->empty() ? v:none :
items->sort((v1, v2) => v1.word < v2.word ? -1 : v1.word ==# v2.word ? 0 : 1)
enddef
```
**Auto-completion:**
Vim's standard completion frequently checks for user input while searching for
new matches. It is responsive irrespective of file size. This makes it
well-suited for smooth auto-completion. You can try with above examples:
```vim
set cot=menuone,popup,noselect inf
autocmd TextChangedI * InsComplete()
def InsComplete()
if getcharstr(1) == '' && getline('.')->strpart(0, col('.') - 1) =~ '\k$'
SkipTextChangedIEvent()
feedkeys("\<c-n>", "n")
endif
enddef
inoremap <silent> <c-e> <c-r>=<SID>SkipTextChangedIEvent()<cr><c-e>
def SkipTextChangedIEvent(): string
# Suppress next event caused by <c-e> (or <c-n> when no matches found)
set eventignore+=TextChangedI
timer_start(1, (_) => {
set eventignore-=TextChangedI
})
return ''
enddef
```
closes: vim/vim#17065
cbe53191d0
Temporarily remove bufname completion with #if 0 to make merging easier.
Co-authored-by: Girish Palya <girishji@gmail.com>
Co-authored-by: Christian Brabandt <cb@256bit.org>
Co-authored-by: glepnir <glephunter@gmail.com>
This commit is contained in:
22
runtime/lua/vim/_meta/options.lua
generated
22
runtime/lua/vim/_meta/options.lua
generated
@ -1027,6 +1027,28 @@ vim.bo.cms = vim.bo.commentstring
|
||||
--- ] tag completion
|
||||
--- t same as "]"
|
||||
--- f scan the buffer names (as opposed to buffer contents)
|
||||
--- f{func} call the function {func}. Multiple "f" flags may be specified.
|
||||
--- Refer to `complete-functions` for details on how the function
|
||||
--- is invoked and what it should return. The value can be the
|
||||
--- name of a function or a `Funcref`. For `Funcref` values,
|
||||
--- spaces must be escaped with a backslash ('\'), and commas with
|
||||
--- double backslashes ('\\') (see `option-backslash`).
|
||||
--- If the Dict returned by the {func} includes {"refresh": "always"},
|
||||
--- the function will be invoked again whenever the leading text
|
||||
--- changes.
|
||||
--- Completion matches are always inserted at the keyword
|
||||
--- boundary, regardless of the column returned by {func} when
|
||||
--- a:findstart is 1. This ensures compatibility with other
|
||||
--- completion sources.
|
||||
--- To make further modifications to the inserted text, {func}
|
||||
--- can make use of `CompleteDonePre`.
|
||||
--- If generating matches is potentially slow, `complete_check()`
|
||||
--- should be used to avoid blocking and preserve editor
|
||||
--- responsiveness.
|
||||
--- f equivalent to using "f{func}", where the function is taken from
|
||||
--- the 'completefunc' option.
|
||||
--- o equivalent to using "f{func}", where the function is taken from
|
||||
--- the 'omnifunc' option.
|
||||
---
|
||||
--- Unloaded buffers are not loaded, thus their autocmds `:autocmd` are
|
||||
--- not executed, this may lead to unexpected completions from some files
|
||||
|
Reference in New Issue
Block a user