Skip to content

Commit

Permalink
Allow running complete_done_after() in normal mode
Browse files Browse the repository at this point in the history
If user selects a completion item and presses <Esc>, the key sequence to
feedkeys() will get run in normal mode. This can be handled with a
<Plug> mapping that resolves to different sequences in normal mode and
insert mode.

As a bonus, the use of <silent> mappings eliminate the message line
garbage from feedkeys.
  • Loading branch information
infmagic2047 committed Jun 14, 2023
1 parent e74bd3c commit a760749
Showing 1 changed file with 27 additions and 9 deletions.
36 changes: 27 additions & 9 deletions autoload/lsp/ui/vim/completion.vim
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,31 @@
"
let s:context = {}

function! s:run_complete_done_after_in_normal_mode() abort
" Only run if we are in regular normal mode (and not visual or operator-pending mode)
if mode(1) ==# 'n'
return printf(":\<C-U>call \<SNR>%d_on_complete_done_after()\<CR>", s:SID())
else
return ''
endif
endfunction

function! s:run_complete_done_after_in_insert_mode() abort
if mode(1)[0] ==# 'i'
return printf("\<C-R>=\<SNR>%d_on_complete_done_after()\<CR>", s:SID())
else
return ''
endif
endfunction

function! lsp#ui#vim#completion#_setup() abort
augroup lsp_ui_vim_completion
autocmd!
autocmd CompleteDone * call s:on_complete_done()
augroup END

nnoremap <silent> <expr> <Plug>(__lsp-internal-on-complete-done-after) <SID>run_complete_done_after_in_normal_mode()
inoremap <silent> <expr> <Plug>(__lsp-internal-on-complete-done-after) <SID>run_complete_done_after_in_insert_mode()
endfunction

function! lsp#ui#vim#completion#_disable() abort
Expand Down Expand Up @@ -56,21 +76,13 @@ function! s:on_complete_done() abort
let s:context['completion_item'] = l:managed_user_data['completion_item']
let s:context['start_character'] = l:managed_user_data['start_character']
let s:context['complete_word'] = l:managed_user_data['complete_word']
call feedkeys(printf("\<C-r>=<SNR>%d_on_complete_done_after()\<CR>", s:SID()), 'n')
call feedkeys("\<Plug>(__lsp-internal-on-complete-done-after)", 'n')
endfunction

"
" Apply textEdit or insertText(snippet) and additionalTextEdits.
"
function! s:on_complete_done_after() abort
" Clear message line. feedkeys above leave garbage on message line.
echo ''

" Ignore process if the mode() is not insert-mode after feedkeys.
if mode(1)[0] !=# 'i'
return ''
endif

let l:done_line = s:context['done_line']
let l:done_line_nr = s:context['done_line_nr']
let l:done_position = s:context['done_position']
Expand All @@ -97,6 +109,11 @@ function! s:on_complete_done_after() abort
" clear completed string if need.
let l:is_expandable = s:is_expandable(l:done_line, l:done_position, l:complete_position, l:completion_item, l:complete_word)
if l:is_expandable
" clear_auto_inserted_text() wants to move the cursor to just after
" complete_position, which in normal mode may need 'onemore' in
" 'virtualedit'.
let l:old_virtualedit = &l:virtualedit
setlocal virtualedit+=onemore
call s:clear_auto_inserted_text(l:done_line, l:done_position, l:complete_position)
endif

Expand Down Expand Up @@ -131,6 +148,7 @@ function! s:on_complete_done_after() abort
\ 'character': l:position['character'] + l:overflow_after,
\ }
\ }
let &l:virtualedit = l:old_virtualedit

if get(l:completion_item, 'insertTextFormat', 1) == 2
" insert Snippet.
Expand Down

0 comments on commit a760749

Please sign in to comment.