"============================================================================= " FILE: handler.vim " AUTHOR: Shougo Matsushita " License: MIT license "============================================================================= function! deoplete#handler#_init() abort augroup deoplete autocmd! autocmd InsertLeave * call s:on_insert_leave() autocmd CompleteDone * call s:on_complete_done() autocmd InsertLeave * call s:completion_timer_stop() augroup END for event in ['InsertEnter', 'BufWritePost', 'DirChanged'] call s:define_on_event(event) endfor call s:define_completion_via_timer('TextChangedI') if g:deoplete#enable_on_insert_enter call s:define_completion_via_timer('InsertEnter') endif if g:deoplete#enable_refresh_always call s:define_completion_via_timer('InsertCharPre') endif " Note: Vim 8 GUI is broken " dummy timer call is needed before complete() if !has('nvim') && has('gui_running') let s:dummy_timer = timer_start(200, {timer -> 0}, {'repeat': -1}) endif if deoplete#util#has_yarp() " To fix "RuntimeError: Event loop is closed" issue " Note: Workaround autocmd deoplete VimLeavePre * call s:kill_yarp() endif endfunction function! deoplete#handler#_do_complete() abort let context = g:deoplete#_context let event = get(context, 'event', '') let modes = (event ==# 'InsertEnter') ? ['n', 'i'] : ['i'] if s:is_exiting() || index(modes, mode()) < 0 call s:completion_timer_stop() return endif if empty(get(context, 'candidates', [])) \ || deoplete#util#get_input(context.event) !=# context.input return endif let prev = g:deoplete#_prev_completion let prev.event = context.event let prev.candidates = context.candidates let prev.complete_position = getpos('.') if context.event ==# 'Manual' let context.event = '' elseif !exists('g:deoplete#_saved_completeopt') call deoplete#mapping#_set_completeopt() endif if g:deoplete#complete_method ==# 'complete' call feedkeys("\_", 'i') elseif g:deoplete#complete_method ==# 'completefunc' let &l:completefunc = 'deoplete#mapping#_completefunc' call feedkeys("\\", 'in') elseif g:deoplete#complete_method ==# 'omnifunc' let &l:omnifunc = 'deoplete#mapping#_completefunc' call feedkeys("\\", 'in') endif endfunction function! s:completion_timer_start(event) abort if exists('s:completion_timer') call s:completion_timer_stop() endif let delay = max([20, g:deoplete#auto_complete_delay]) let s:completion_timer = timer_start( \ delay, {-> s:completion_begin(a:event)}) endfunction function! s:completion_timer_stop() abort if !exists('s:completion_timer') return endif call timer_stop(s:completion_timer) unlet s:completion_timer endfunction function! deoplete#handler#_async_timer_start() abort if exists('s:async_timer') call deoplete#handler#_async_timer_stop() endif let s:async_timer = { 'event': 'Async', 'changedtick': b:changedtick } let s:async_timer.id = timer_start( \ max([20, g:deoplete#auto_refresh_delay]), \ function('s:completion_async'), {'repeat': -1}) endfunction function! deoplete#handler#_async_timer_stop() abort if exists('s:async_timer') call timer_stop(s:async_timer.id) unlet s:async_timer endif endfunction function! s:completion_async(timer) abort if mode() !=# 'i' || s:is_exiting() call deoplete#handler#_async_timer_stop() return endif call s:completion_begin(s:async_timer.event) endfunction function! s:completion_begin(event) abort if s:is_skip(a:event) call deoplete#mapping#_restore_completeopt() let g:deoplete#_context.candidates = [] return endif let context = deoplete#init#_context(a:event, []) if s:check_omnifunc(context) return endif call deoplete#util#rpcnotify( \ 'deoplete_auto_completion_begin', context) endfunction function! s:is_skip(event) abort if s:is_skip_text(a:event) return 1 endif let disable_auto_complete = \ deoplete#util#get_simple_buffer_config( \ 'b:deoplete_disable_auto_complete', \ 'g:deoplete#disable_auto_complete') if &paste \ || (a:event !=# 'Manual' && a:event !=# 'Async' \ && disable_auto_complete) \ || (&l:completefunc !=# '' && &l:buftype =~# 'nofile') \ || (a:event !=# 'InsertEnter' && mode() !=# 'i') return 1 endif return 0 endfunction function! s:is_skip_text(event) abort let context = g:deoplete#_context let input = deoplete#util#get_input(a:event) if has_key(context, 'input') \ && a:event !=# 'Manual' \ && a:event !=# 'Async' \ && input ==# context.input return 1 endif let displaywidth = strdisplaywidth(input) + 1 if &l:formatoptions =~# '[tca]' && &l:textwidth > 0 \ && displaywidth >= &l:textwidth if &l:formatoptions =~# '[ta]' \ || !empty(filter(deoplete#util#get_syn_names(), \ "v:val ==# 'Comment'")) return 1 endif endif let skip_chars = deoplete#util#get_simple_buffer_config( \ 'b:deoplete_skip_chars', 'g:deoplete#skip_chars') return (!pumvisible() && virtcol('.') != displaywidth) \ || (a:event !=# 'Manual' && input !=# '' \ && index(skip_chars, input[-1:]) >= 0) endfunction function! s:check_omnifunc(context) abort let prev = g:deoplete#_prev_completion let blacklist = ['LanguageClient#complete'] if prev.event ==# 'Manual' \ || &l:omnifunc ==# '' \ || index(blacklist, &l:omnifunc) >= 0 \ || prev.complete_position ==# getpos('.') return endif for filetype in a:context.filetypes for pattern in deoplete#util#convert2list( \ deoplete#util#get_buffer_config(filetype, \ 'b:deoplete_omni_patterns', \ 'g:deoplete#omni_patterns', \ 'g:deoplete#_omni_patterns')) if pattern !=# '' && a:context.input =~# '\%('.pattern.'\)$' let g:deoplete#_context.candidates = [] let prev.event = a:context.event let prev.candidates = [] let prev.complete_position = getpos('.') call deoplete#mapping#_set_completeopt() call feedkeys("\\", 'in') return 1 endif endfor endfor endfunction function! s:define_on_event(event) abort if !exists('##' . a:event) return endif execute 'autocmd deoplete' a:event \ '* call deoplete#send_event('.string(a:event).')' endfunction function! s:define_completion_via_timer(event) abort if !exists('##' . a:event) return endif execute 'autocmd deoplete' a:event \ '* call s:completion_timer_start('.string(a:event).')' endfunction function! s:on_insert_leave() abort call deoplete#mapping#_restore_completeopt() let g:deoplete#_context = {} let g:deoplete#_prev_completion = { \ 'complete_position': [], \ 'candidates': [], \ 'event': '', \ } endfunction function! s:on_complete_done() abort if get(v:completed_item, 'word', '') ==# '' return endif let word = v:completed_item.word if !has_key(g:deoplete#_rank, word) let g:deoplete#_rank[word] = 1 else let g:deoplete#_rank[word] += 1 endif endfunction function! deoplete#handler#_skip_next_completion() abort if !exists('g:deoplete#_context') return endif let input = deoplete#util#get_input('CompleteDone') if input[-1:] !=# '/' let g:deoplete#_context.input = input endif endfunction function! s:is_exiting() abort return exists('v:exiting') && v:exiting != v:null endfunction function! s:kill_yarp() abort if g:deoplete#_yarp.job_is_dead return endif let job = g:deoplete#_yarp.job if !has('nvim') && !exists('g:yarp_jobstart') " Get job object from vim-hug-neovim-rpc let job = g:_neovim_rpc_jobs[job].job endif if has('nvim') call jobstop(job) else call job_stop(job, 'kill') endif let g:deoplete#_yarp.job_is_dead = 1 endfunction