Skip to content

Commit 874a63d

Browse files
committed
Allow running complete_done_after() in normal mode
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.
1 parent ad6d61b commit 874a63d

File tree

1 file changed

+27
-9
lines changed

1 file changed

+27
-9
lines changed

autoload/lsp/ui/vim/completion.vim

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,31 @@
22
"
33
let s:context = {}
44

5+
function! s:run_complete_done_after_in_normal_mode() abort
6+
" Only run if we are in regular normal mode (and not visual or operator-pending mode)
7+
if mode(1) ==# 'n'
8+
return printf(":\<C-U>call \<SNR>%d_on_complete_done_after()\<CR>", s:SID())
9+
else
10+
return ''
11+
endif
12+
endfunction
13+
14+
function! s:run_complete_done_after_in_insert_mode() abort
15+
if mode(1)[0] ==# 'i'
16+
return printf("\<C-R>=\<SNR>%d_on_complete_done_after()\<CR>", s:SID())
17+
else
18+
return ''
19+
endif
20+
endfunction
21+
522
function! lsp#ui#vim#completion#_setup() abort
623
augroup lsp_ui_vim_completion
724
autocmd!
825
autocmd CompleteDone * call s:on_complete_done()
926
augroup END
27+
28+
nnoremap <silent> <expr> <Plug>(__lsp-internal-on-complete-done-after) <SID>run_complete_done_after_in_normal_mode()
29+
inoremap <silent> <expr> <Plug>(__lsp-internal-on-complete-done-after) <SID>run_complete_done_after_in_insert_mode()
1030
endfunction
1131

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

6282
"
6383
" Apply textEdit or insertText(snippet) and additionalTextEdits.
6484
"
6585
function! s:on_complete_done_after() abort
66-
" Clear message line. feedkeys above leave garbage on message line.
67-
echo ''
68-
69-
" Ignore process if the mode() is not insert-mode after feedkeys.
70-
if mode(1)[0] !=# 'i'
71-
return ''
72-
endif
73-
7486
let l:done_line = s:context['done_line']
7587
let l:done_line_nr = s:context['done_line_nr']
7688
let l:completed_item = s:context['completed_item']
@@ -97,6 +109,11 @@ function! s:on_complete_done_after() abort
97109
" clear completed string if need.
98110
let l:is_expandable = s:is_expandable(l:done_line, l:done_position, l:complete_position, l:completion_item, l:completed_item)
99111
if l:is_expandable
112+
" clear_auto_inserted_text() wants to move the cursor to just after
113+
" complete_position, which in normal mode may need 'onemore' in
114+
" 'virtualedit'.
115+
let l:old_virtualedit = &l:virtualedit
116+
setlocal virtualedit+=onemore
100117
call s:clear_auto_inserted_text(l:done_line, l:done_position, l:complete_position)
101118
endif
102119

@@ -131,6 +148,7 @@ function! s:on_complete_done_after() abort
131148
\ 'character': l:position['character'] + l:overflow_after,
132149
\ }
133150
\ }
151+
let &l:virtualedit = l:old_virtualedit
134152

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

0 commit comments

Comments
 (0)