]> Sergey Matveev's repositories - vim-lsp.git/commitdiff
Trigger insert mode completion automatically
authorYegappan Lakshmanan <yegappan@yahoo.com>
Tue, 26 Jan 2021 05:14:24 +0000 (21:14 -0800)
committerYegappan Lakshmanan <yegappan@yahoo.com>
Tue, 26 Jan 2021 05:14:24 +0000 (21:14 -0800)
autoload/handlers.vim
autoload/lsp.vim
autoload/lspserver.vim

index 6965569b1660f9a54c49a7da5ffd0d99cb2a8db8..d7c01659b4d472cc3ad0444c900b4376dc86f0a5 100644 (file)
@@ -32,12 +32,9 @@ def s:processInitializeReply(lspserver: dict<any>, req: dict<any>, reply: dict<a
     endfor
   endif
 
-  # map characters that trigger insert mode completion
   if caps->has_key('completionProvider')
-    var triggers = caps.completionProvider.triggerCharacters
-    for ch in triggers
-      exe 'inoremap <buffer> <silent> ' .. ch .. ' ' .. ch .. "<C-X><C-U>"
-    endfor
+    lspserver.completionTriggerChars =
+                               caps.completionProvider.triggerCharacters
   endif
 
   # send a "initialized" notification to server
@@ -159,6 +156,7 @@ def s:processCompletionReply(lspserver: dict<any>, req: dict<any>, reply: dict<a
     items = reply.result.items
   endif
 
+  var completeItems: list<dict<any>> = []
   for item in items
     var d: dict<any> = {}
     if item->has_key('textEdit') && item.textEdit->has_key('newText')
@@ -185,10 +183,32 @@ def s:processCompletionReply(lspserver: dict<any>, req: dict<any>, reply: dict<a
        d.info = item.documentation.value
       endif
     endif
-    lspserver.completeItems->add(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
index 4094178de364444cf959aaea7157e6905facbe73..e37669b00e29665a9427a0168e5bd3217ba32f44 100644 (file)
@@ -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 <buffer=' .. bnr
+       .. '> 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 <buffer> <silent> ' .. ch .. ' ' .. ch .. "<C-X><C-U>"
-    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<any> = 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<dict<any>> = []
-    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
index 0c198b3d95547a5fcec52b07e5706cee65137ac2..44f16916b23526b66967906db8cc016f1264fdeb 100644 (file)
@@ -57,7 +57,6 @@ def s:startServer(lspserver: dict<any>): 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<string>): dict<any>
     nextID: 1,
     caps: {},
     requests: {},
-    completePending: v:false,
     diagsMap: {},
+    completionTriggerChars: [],
     workspaceSymbolPopup: 0,
     workspaceSymbolQuery: ''
   }