Files
ii41 52a627924c Clear matches and enable closing popup menu (#230)
* Remove "skip popup" related logic

* Fix matches not getting cleared

Before this commit we don't clear the matches when the text
under the cursor is no longer suitable for completion. This
causes e.g. removing everything using <BS> does not close
the completion menu.

* Allow closing popup menu

Closing popup menu calls completion itself, making it
impossible to be successful.

We used to have a "skip popup" logic to fix this. It was
removed 2 commits ago for being too confusing.

To fix this a check is adapted to make sure that completion
is only called when the completion context has changed.
Since closing popup menu does not change the completion
context, it no longer calls completion, and therefore can
succeed.

Previously this check lets us not complete when we move to a
different line we are in insert mode, through for example
<CR> or <BS>, but actually we are not afraid of this. When
we enter a newline, we don't complete anyway since the
refresh pattern is not matched, and when we backspace to a
previous line, and the line happens to end with something
that will trigger a completion, why do we not want to
trigger it?

* Also compare completion base to determine context change

It is possible that in some situation changing the text under the
cursor does not change the position of the cursor, so we also
compare the completion base to determine whether the context has
changed.
2020-10-17 09:57:48 -07:00

79 lines
2.5 KiB
VimL

let s:callbacks = []
function! asyncomplete#utils#_on_change#textchangedp#init() abort
if exists('##TextChangedP')
call s:setup_if_required()
return {
\ 'name': 'TextChangedP',
\ 'register': function('s:register'),
\ 'unregister': function('s:unregister'),
\ }
else
return { 'name': 'TextChangedP', 'error': 'Requires vim with TextChangedP support' }
endif
endfunction
function! s:setup_if_required() abort
augroup asyncomplete_utils_on_change_text_changed_p
autocmd!
autocmd InsertEnter * call s:on_insert_enter()
autocmd InsertLeave * call s:on_insert_leave()
autocmd TextChangedI * call s:on_text_changed_i()
autocmd TextChangedP * call s:on_text_changed_p()
augroup END
endfunction
function! s:register(cb) abort
call add(s:callbacks , a:cb)
endfunction
function! s:unregister(obj, cb) abort
" TODO: remove from s:callbacks
endfunction
function! s:on_insert_enter() abort
let l:context = asyncomplete#context()
let s:previous_context = {
\ 'lnum': l:context['lnum'],
\ 'col': l:context['col'],
\ 'typed': l:context['typed'],
\ }
endfunction
function! s:on_insert_leave() abort
unlet s:previous_context
endfunction
function! s:on_text_changed_i() abort
call s:maybe_notify_on_change()
endfunction
function! s:on_text_changed_p() abort
call s:maybe_notify_on_change()
endfunction
function! s:maybe_notify_on_change() abort
" We notify on_change callbacks only when the cursor position
" has changed.
" Unfortunatelly we need this check because in insert mode it
" is possible to have TextChangedI triggered when the completion
" context is not changed at all: When we close the completion
" popup menu via <C-e> or <C-y>. If we still let on_change
" do the completion in this case we never close the menu.
" Vim doesn't allow programmatically changing buffer content
" in insert mode, so by comparing the cursor's position and the
" completion base we know whether the context has changed.
let l:context = asyncomplete#context()
let l:previous_context = s:previous_context
let s:previous_context = {
\ 'lnum': l:context['lnum'],
\ 'col': l:context['col'],
\ 'typed': l:context['typed'],
\ }
if l:previous_context !=# s:previous_context
for l:Cb in s:callbacks
call l:Cb()
endfor
endif
endfunction