]> Sergey Matveev's repositories - vim-lsp.git/commitdiff
Instead of always trying to complete symbols, use omni completion
authorYegappan Lakshmanan <yegappan@yahoo.com>
Fri, 29 Jan 2021 05:28:01 +0000 (21:28 -0800)
committerYegappan Lakshmanan <yegappan@yahoo.com>
Fri, 29 Jan 2021 05:28:01 +0000 (21:28 -0800)
autoload/handlers.vim
autoload/lsp.vim
autoload/lspserver.vim
doc/lsp.txt

index dd86f4a278466be39cb7973eaf92548cfac49cba..944e51bde91fa2804d2074d0ed2662305c10bb53 100644 (file)
@@ -32,11 +32,17 @@ 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-O>"
+    endfor
     lspserver.completionTriggerChars =
                                caps.completionProvider.triggerCharacters
   endif
 
+
   # send a "initialized" notification to server
   lspserver.sendInitializedNotif()
 
@@ -156,7 +162,6 @@ 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')
@@ -183,35 +188,10 @@ def s:processCompletionReply(lspserver: dict<any>, req: dict<any>, reply: dict<a
        d.info = item.documentation.value
       endif
     endif
-    completeItems->add(d)
-  endfor
-
-  if completeItems->empty()
-    return
-  endif
-
-  # Find the start column for the completion.  If any of the entries returned
-  # by the LSP server has a starting position, then use that.
-  var start_col: number = 0
-  for item in items
-    if item->has_key('textEdit')
-      start_col = item.textEdit.range.start.character + 1
-      break
-    endif
+    lspserver.completeItems->add(d)
   endfor
 
-  # LSP server didn't return a starting position for completion, search
-  # backwards from the current cursor position for a non-keyword character.
-  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 + 1
-  endif
-
-  complete(start_col, completeItems)
+  lspserver.completePending = false
 enddef
 
 # process the 'textDocument/hover' reply from the LSP server
index f551ca31f69f2e12b9c9e2b38a1bced0e6ab0299..0e04d61957ab3baf7481613f9ab8a7f336de31e0 100644 (file)
@@ -276,11 +276,9 @@ def lsp#addFile(bnr: number): void
   # add a listener to track changes to this buffer
   listener_add(function('lsp#bufchange_listener'), bnr)
   setbufvar(bnr, '&completeopt', 'menuone,popup,noinsert,noselect')
+  setbufvar(bnr, '&omnifunc', 'lsp#omniFunc')
   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'
   exe 'autocmd InsertLeave <buffer=' .. bnr .. '> call lsp#leftInsertMode()'
 
   # map characters that trigger signature help
@@ -526,35 +524,50 @@ def lsp#jumpToDiag(which: string): void
   WarnMsg('Error: No more diagnostics found')
 enddef
 
-# Insert mode completion handler
-def lsp#complete(): string
-  var cur_col: number = col('.')
-  var line: string = getline('.')
-
-  if cur_col == 0 || line->empty()
-    return ''
-  endif
-
+# omni complete handler
+def lsp#omniFunc(findstart: number, base: string): any
   var ftype: string = &filetype
   var lspserver: dict<any> = s:lspGetServer(ftype)
 
-  if lspserver->empty() || !lspserver.running || lspserver.caps->empty()
-    return ''
-  endif
-
-  if line[cur_col - 2] !~ '\k'
-    if lspserver.completionTriggerChars->index(line[cur_col - 2]) == -1
-      return ''
+  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
-  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 ''
+    # 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
+  endif
 enddef
 
 # Display the hover message from the LSP server for the current cursor
index 3a24e6ca6f7a70afad2c424c079abbc9543a8430..922c0b58ce3e5bf00d227070ea7a730b9dcdc98d 100644 (file)
@@ -57,6 +57,7 @@ def s:startServer(lspserver: dict<any>): number
   lspserver.caps = {}
   lspserver.nextID = 1
   lspserver.requests = {}
+  lspserver.completePending = false
   lspserver.workspaceFolders = [getcwd()]
 
   var job = job_start(cmd, opts)
@@ -789,8 +790,8 @@ export def NewLspServer(path: string, args: list<string>): dict<any>
     nextID: 1,
     caps: {},
     requests: {},
+    completePending: false,
     diagsMap: {},
-    completionTriggerChars: [],
     workspaceSymbolPopup: 0,
     workspaceSymbolQuery: ''
   }
index 0dd85b643ea63f20ca82026568abf6ef14deae5a..2c0bb057084a475d9eece9ddb7ccc7b5f5150091 100644 (file)
@@ -343,6 +343,14 @@ accepts a list of LSP servers with the above information.
 :LspWorkspaceListFolders
                        Show the list of folders in the workspace.
 
+==============================================================================
+6. Insert mode completion
+
+The LSP plugin sets the 'omnifunc' option for the buffers which have a
+registered LSP server. To complete a symbol in insert mode, you can press
+CTRL-X CTRL-O to invoke completion using the items suggested by the LSP
+server.
+
 ==============================================================================
 
 vim:tw=78:ts=8:noet:ft=help:norl: