Sonraki araştırmalardan sonra (ve tersine mühendislik).
Tamamlamanın neden belgeleri tam olarak takip etmediğini açıklayamıyorum. Sanırım vim_dev'e sormam gerekecek.
Her neyse, bunu yapmanın yolu, CursorMovedI
her karakter eklendiğinde tekrar tamamlamayı tetikleyecek bir dinleyiciyi kaydetmekten ibarettir .
Zorluk o zaman ne zaman duracağını bilmek.
CompletionDone
her tuş vuruşundan sonra tetikleneceğinden hiçbir faydası yoktur.
InsertLeave
iyi bir başlangıçtır, ancak tüm durumları kapsamaz, yani
- Eşleşmesi olmayan bir karakter yazıldığında, durmamız gerekir
- Son kullanıcı bir menü öğesi seçtiğinde de durmamız gerekir.
Geçersiz kılmanın dışında bir yol bulamadım <cr>
ve <c-y>
.
Diğer zorluklar, tür sonsuz döngülerden kaçınmak için hiçbir şeyin değişmediğini tespit etmektir.
Her neyse, işte mevcut kodum (diğer eklentilerde kullanılacak). Geçen sürüm burada muhafaza edilecektir . Oldukça uzun, ama işte burada:
" ## Smart completion {{{2
" Function: lh#icomplete#new(startcol, matches, hook) {{{3
function! lh#icomplete#new(startcol, matches, hook) abort
silent! unlet b:complete_data
let augroup = 'IComplete'.bufnr('%').'Done'
let b:complete_data = lh#on#exit()
\.restore('&completefunc')
\.restore('&complete')
\.restore('&omnifunc')
\.register('au! '.augroup)
\.register('call self.logger.log("finalized! (".getline(".").")")')
set complete=
let b:complete_data.startcol = a:startcol
let b:complete_data.all_matches = map(copy(a:matches), 'type(v:val)==type({}) ? v:val : {"word": v:val}')
let b:complete_data.matches = {'words': [], 'refresh': 'always'}
let b:complete_data.hook = a:hook
let b:complete_data.cursor_pos = []
let b:complete_data.last_content = [line('.'), getline('.')]
let b:complete_data.no_more_matches = 0
let b:complete_data.logger = s:logger.reset()
" keybindings {{{4
call b:complete_data
\.restore_buffer_mapping('<cr>', 'i')
\.restore_buffer_mapping('<c-y>', 'i')
\.restore_buffer_mapping('<esc>', 'i')
\.restore_buffer_mapping('<tab>', 'i')
inoremap <buffer> <silent> <cr> <c-y><c-\><c-n>:call b:complete_data.conclude()<cr>
inoremap <buffer> <silent> <c-y> <c-y><c-\><c-n>:call b:complete_data.conclude()<cr>
" Unlike usual <tab> behaviour, this time, <tab> inserts the next match
inoremap <buffer> <silent> <tab> <down><c-y><c-\><c-n>:call b:complete_data.conclude()<cr>
" <c-o><Nop> doesn't work as expected...
" To stay in INSERT-mode:
" inoremap <silent> <esc> <c-e><c-o>:<cr>
" To return into NORMAL-mode:
inoremap <buffer> <silent> <esc> <c-e><esc>
" TODO: see to have <Left>, <Right>, <Home>, <End> abort
" Group {{{4
exe 'augroup '.augroup
au!
" Emulate InsertCharPost
" au CompleteDone <buffer> call b:complete_data.logger.log("Completion done")
au InsertLeave <buffer> call b:complete_data.finalize()
au CursorMovedI <buffer> call b:complete_data.cursor_moved()
augroup END
function! s:cursor_moved() abort dict "{{{4
if self.no_more_matches
call self.finalize()
return
endif
if !self.has_text_changed_since_last_move()
call s:logger.log(lh#fmt#printf("cursor %1 just moved (text hasn't changed)", string(getpos('.'))))
return
endif
call s:logger.log(lh#fmt#printf('cursor moved %1 and text has changed -> relaunch completion', string(getpos('.'))))
call feedkeys( "\<C-X>\<C-O>\<C-P>\<Down>", 'n' )
endfunction
let b:complete_data.cursor_moved = function('s:cursor_moved')
function! s:has_text_changed_since_last_move() abort dict "{{{4
let l = line('.')
let line = getline('.')
try
if l != self.last_content[0] " moved vertically
let self.no_more_matches = 1
call s:logger.log("Vertical move => stop")
return 0
" We shall leave complete mode now!
endif
call s:logger.log(lh#fmt#printf("line was: %1, and becomes: %2; has_changed?%3", self.last_content[1], line, line != self.last_content[1]))
return line != self.last_content[1] " text changed
finally
let self.last_content = [l, line]
endtry
endfunction
let b:complete_data.has_text_changed_since_last_move = function('s:has_text_changed_since_last_move')
function! s:complete(findstart, base) abort dict "{{{4
call s:logger.log(lh#fmt#printf('findstart?%1 -> %2', a:findstart, a:base))
if a:findstart
if self.no_more_matches
call s:logger.log("no more matches -> -3")
return -3
call self.finalize()
endif
if self.cursor_pos == getcurpos()
call s:logger.log("cursor hasn't moved -> -2")
return -2
endif
let self.cursor_pos = getcurpos()
return self.startcol
else
return self.get_completions(a:base)
endif
endfunction
let b:complete_data.complete = function('s:complete')
function! s:get_completions(base) abort dict "{{{4
let matching = filter(copy(self.all_matches), 'v:val.word =~ join(split(a:base, ".\\zs"), ".*")')
let self.matches.words = matching
call s:logger.log(lh#fmt#printf("'%1' matches: %2", a:base, string(self.matches)))
if empty(self.matches.words)
call s:logger.log("No more matches...")
let self.no_more_matches = 1
endif
return self.matches
endfunction
let b:complete_data.get_completions = function('s:get_completions')
function! s:conclude() abort dict " {{{4
let selection = getline('.')[self.startcol : col('.')-1]
call s:logger.log("Successful selection of <".selection.">")
if !empty(self.hook)
call lh#function#execute(self.hook, selection)
endif
" call self.hook()
call self.finalize()
endfunction
let b:complete_data.conclude = function('s:conclude')
" Register {{{4
" call b:complete_data
" \.restore('b:complete_data')
" set completefunc=lh#icomplete#func
set omnifunc=lh#icomplete#func
endfunction
" Function: lh#icomplete#new_on(pattern, matches, hook) {{{3
function! lh#icomplete#new_on(pattern, matches, hook) abort
let l = getline('.')
let startcol = match(l[0:col('.')-1], '\v'.a:pattern.'+$')
if startcol == -1
let startcol = col('.')-1
endif
call lh#icomplete#new(startcol, a:matches, a:hook)
endfunction
" Function: lh#icomplete#func(startcol, base) {{{3
function! lh#icomplete#func(findstart, base) abort
return b:complete_data.complete(a:findstart, a:base)
endfunction
Hangi ile kullanılabilir:
let entries = [
\ {'word': 'un', 'menu': 1},
\ {'word': 'deux', 'menu': 2},
\ {'word': 'trois', 'menu': 3},
\ {'word': 'trentre-deux', 'menu': 32},
\ 'unité'
\ ]
inoremap <silent> <buffer> µ <c-o>:call lh#icomplete#new_on('\w', entries, 'lh#common#warning_msg("nominal: ".v:val)')<cr><c-x><c-O><c-p><down>
Bu screencast'ta şablon genişletici eklentim için C ++ snippet seçimine uygulanan sonucu (dolaylı olarak) gözlemleyebilmelisiniz .