From c5de025ca8784fb50d6b47be3103fa322d07ce37 Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Mon, 25 Jan 2021 21:14:24 -0800 Subject: [PATCH] Trigger insert mode completion automatically --- autoload/handlers.vim | 34 ++++++++++++++++---- autoload/lsp.vim | 73 +++++++++++++++--------------------------- autoload/lspserver.vim | 3 +- 3 files changed, 54 insertions(+), 56 deletions(-) diff --git a/autoload/handlers.vim b/autoload/handlers.vim index 6965569..d7c0165 100644 --- a/autoload/handlers.vim +++ b/autoload/handlers.vim @@ -32,12 +32,9 @@ def s:processInitializeReply(lspserver: dict, req: dict, reply: dicthas_key('completionProvider') - var triggers = caps.completionProvider.triggerCharacters - for ch in triggers - exe 'inoremap ' .. ch .. ' ' .. ch .. "" - endfor + lspserver.completionTriggerChars = + caps.completionProvider.triggerCharacters endif # send a "initialized" notification to server @@ -159,6 +156,7 @@ def s:processCompletionReply(lspserver: dict, req: dict, reply: dict> = [] for item in items var d: dict = {} if item->has_key('textEdit') && item.textEdit->has_key('newText') @@ -185,10 +183,32 @@ def s:processCompletionReply(lspserver: dict, req: dict, reply: dictadd(d) + completeItems->add(d) endfor - lspserver.completePending = v:false + if completeItems->empty() + return + endif + + # Find the start column for the completion + var start_col: number = 0 + for item in items + if item->has_key('textEdit') + start_col = item.textEdit.range.start.character + 1 + break + endif + endfor + + if start_col == 0 + var line: string = getline('.') + var start = col('.') - 1 + while start > 0 && line[start - 1] =~ '\k' + start -= 1 + endwhile + start_col = start + endif + + complete(start_col, completeItems) enddef # process the 'textDocument/hover' reply from the LSP server diff --git a/autoload/lsp.vim b/autoload/lsp.vim index 4094178..e37669b 100644 --- a/autoload/lsp.vim +++ b/autoload/lsp.vim @@ -255,10 +255,12 @@ def lsp#addFile(bnr: number): void # add a listener to track changes to this buffer listener_add(function('lsp#bufchange_listener'), bnr) - setbufvar(bnr, '&completefunc', 'lsp#completeFunc') setbufvar(bnr, '&completeopt', 'menuone,popup,noinsert,noselect') setbufvar(bnr, '&completepopup', 'border:off') setbufvar(bnr, '&balloonexpr', 'LspDiagExpr()') + # autocmd for insert mode completion + exe 'autocmd SafeState if mode() == "i" | call lsp#complete() | endif' # map characters that trigger signature help if lspserver.caps->has_key('signatureHelpProvider') @@ -269,14 +271,6 @@ def lsp#addFile(bnr: number): void endfor endif - # map characters that trigger insert mode completion - if lspserver.caps->has_key('completionProvider') - var triggers = lspserver.caps.completionProvider.triggerCharacters - for ch in triggers - exe 'inoremap ' .. ch .. ' ' .. ch .. "" - endfor - endif - bufnrToServer[bnr] = lspserver enddef @@ -512,49 +506,34 @@ def lsp#jumpToDiag(which: string): void enddef # Insert mode completion handler -def lsp#completeFunc(findstart: number, base: string): any +def lsp#complete(): string + var cur_col: number = col('.') + var line: string = getline('.') + + if cur_col == 0 || line->empty() + return '' + endif + var ftype: string = &filetype var lspserver: dict = s:lspGetServer(ftype) - if findstart - if lspserver->empty() - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not found') - return -2 - endif - if !lspserver.running - ErrMsg('Error: LSP server for "' .. ftype .. '" filetype is not running') - return -2 - endif + if lspserver->empty() || !lspserver.running || lspserver.caps->empty() + return '' + endif - # first send all the changes in the current buffer to the LSP server - listener_flush() - - lspserver.completePending = v:true - lspserver.completeItems = [] - # initiate a request to LSP server to get list of completions - lspserver.getCompletion() - - # locate the start of the word - var line = getline('.') - var start = charcol('.') - 1 - while start > 0 && line[start - 1] =~ '\k' - start -= 1 - endwhile - return start - else - var count: number = 0 - while !complete_check() && lspserver.completePending - && count < 1000 - sleep 2m - count += 1 - endwhile - - var res: list> = [] - for item in lspserver.completeItems - res->add(item) - endfor - return res->empty() ? v:none : res + if line[cur_col - 2] !~ '\k' + if lspserver.completionTriggerChars->index(line[cur_col - 2]) == -1 + return '' + endif endif + + # first send all the changes in the current buffer to the LSP server + listener_flush() + + # initiate a request to LSP server to get list of completions + lspserver.getCompletion() + + return '' enddef # Display the hover message from the LSP server for the current cursor diff --git a/autoload/lspserver.vim b/autoload/lspserver.vim index 0c198b3..44f1691 100644 --- a/autoload/lspserver.vim +++ b/autoload/lspserver.vim @@ -57,7 +57,6 @@ def s:startServer(lspserver: dict): number lspserver.caps = {} lspserver.nextID = 1 lspserver.requests = {} - lspserver.completePending = v:false lspserver.workspaceFolders = [getcwd()] var job = job_start(cmd, opts) @@ -790,8 +789,8 @@ export def NewLspServer(path: string, args: list): dict nextID: 1, caps: {}, requests: {}, - completePending: v:false, diagsMap: {}, + completionTriggerChars: [], workspaceSymbolPopup: 0, workspaceSymbolQuery: '' } -- 2.48.1