Dinamik tamamlama


12

Eski bir tamamlama işlevini geliştirmeye çalışıyorum. Yeni karakterler yazarken açılır menüde görüntülenen seçenekleri güncellemek istiyorum

Tamamlama fonksiyonum

function! lh#icomplete#ecm(findstart, base) abort
  if a:findstart
    let l = getline('.')
    let startcol = match(l[0:col('.')-1], '\v\S+$')
    if startcol == -1
      let startcol = col('.')-1
    endif
    " let g:debug+= ["findstart(".a:base.") -> ".(startcol)]
    return startcol
  else
    " let g:debug += ["matching(".a:base.")"]
    let words = ['un', 'deux', 'trois', 'trente-deux', 'unité']
    call filter(words, 'v:val =~ a:base')
    " return { 'words' : words}
    return { 'words' : words, 'refresh' : 'always'}
  endif
endfunction

Birlikte kullandığım

:set completefunc=lh#icomplete#ecm
:inoremap µ <c-x><c-u><c-p>

Dokümantasyon, kullandığım aslında Benim anlayış <c-p>, ben gitmek üçüncü devlet (| ins tamamlama menü | göre), ve ne zaman yazın "Herhangi bir yazdırılabilir, beyaz olmayan bir karakter" Ben mümkün olmalıdır Ekle" bu karakteri ve eşleşme sayısını azaltın. "

Ekleme moduna yazdığımda , tamamlanma menüsü beklendiği gibi açılır. Yazarken x(hemen sonra µ) ne yazık ki , tamamlanma modundan çıkıyorum ve uxarabelleğimde aldım.

Belgelerde neyi yanlış yaptım ya da kaçırdım?

Not: refresh=alwaysÖzel bir filtre uygulamak için işlevi tekrar çağırmak dışında, sonuçların filtrelendiğini gördüm .

(Her ihtimale karşı gvim 7.4-908 kullanıyorum)


Bu bir hata gibi görünüyor. Benim için de işe yaramıyor (Vim 7.4.944'teyim).
Karl Yngve Lervåg

Çalışmalı mı? Bilmiyorum bu.
Luc Hermitte

Dokümantasyonun çalışması gerektiği anlamına geliyor.
Karl Yngve Lervåg

Yanıtlar:


3

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.