]> Sergey Matveev's repositories - vim-lsp.git/commitdiff
Make buffer completion responsive for large files
authorGirish Palya <girishji@gmail.com>
Sun, 25 Jun 2023 11:26:37 +0000 (13:26 +0200)
committerGirish Palya <girishji@gmail.com>
Sun, 25 Jun 2023 11:26:37 +0000 (13:26 +0200)
Since buffer completion processes the current buffer everytime user
types something, it will degrade the experience for large files.

This change adds a timeout to buffer completor function. Processing
current buffer is cut short when timeout is exceeded. Setting
timeout to 0 will revert back to existing behaviour.

Default is set to 100 ms, good for scanning 6000 lines on M1 macbook.

It is possible to get fancy by scanning locality of cursor first
but such complication may not be worth the complexity.

Tested on >20k line files (I have to open these large C files
filled with hw specs occasionally).

M  autoload/lsp/completion.vim
M  autoload/lsp/options.vim
M  doc/lsp.txt

autoload/lsp/completion.vim
autoload/lsp/options.vim
doc/lsp.txt

index 66ea9c5d6d23ec9b74289171a576965915153aeb..9b2d598f512caea8a1d4cc853fabb7ea98ea8a32 100644 (file)
@@ -114,22 +114,30 @@ enddef
 
 # add completion from current buf
 def CompletionFromBuffer(items: list<dict<any>>)
-    var words = {}
-    for line in getline(1, '$')
-        for word in line->split('\W\+')
-            if !words->has_key(word) && word->len() > 1
-                words[word] = 1
-                items->add({
-                    label: word,
-                    data: {
-                        entryNames: [word],
-                    },
-                    kind: 26,
-                    documentation: "",
-                })
-            endif
-        endfor
+  var words = {}
+  var start = reltime()
+  var linenr = 1
+  for line in getline(1, '$')
+    for word in line->split('\W\+')
+      if !words->has_key(word) && word->len() > 1
+       words[word] = 1
+       items->add({
+         label: word,
+         data: {
+           entryNames: [word],
+         },
+         kind: 26,
+         documentation: "",
+       })
+      endif
     endfor
+    # Check every 200 lines if timeout is exceeded
+    if opt.lspOptions.bufferCompletionTimeout > 0 && linenr % 200 == 0 && 
+       start->reltime()->reltimefloat() * 1000 > opt.lspOptions.bufferCompletionTimeout
+      break
+    endif
+    linenr += 1
+  endfor
 enddef
 
 # process the 'textDocument/completion' reply from the LSP server
index 8ccf7e478331da564d84774d7b6b788663569aca..be55f058a40a4723dc51ee30d5fb4e8718377db8 100644 (file)
@@ -77,6 +77,8 @@ export var lspOptions: dict<any> = {
   useQuickfixForLocations: false,
   # add to autocomplition list current buffer words
   useBufferCompletion: false,
+  # Limit the time autocompletion searches for words in current buffer (in milliseconds)
+  bufferCompletionTimeout: 100,
   # Enable support for custom completion kinds
   customCompletionKinds: false,
   # A dictionary with all completion kinds that you want to customize
index 910dcd1fc3690d1f7ac4100808bca1ded490b85e..3c212fb279bc95691fa0e4a70b3491b057efbe3a 100644 (file)
@@ -589,10 +589,17 @@ useQuickfixForLocations   |Boolean| option.  Show |:LspShowReferences| in a
                                                *lsp-opt-useBufferCompletion*
 useBufferCompletion     |Boolean| option. If enabled, the words from the
                        current buffer are added to the auto completion list.
-                       This may degrade Vim performance as the current buffer
-                       contents are processed every time the completion menu
-                       is displayed.
                        By default this is set to false.
+                                               *lsp-opt-bufferCompletionTimeout*
+bufferCompletionTimeout |Number| option. Specifies how long (in milliseconds) 
+                       to wait while processing current buffer for 
+                       autocompletion words.  If set too high Vim performance
+                       may degrade as the current buffer contents are
+                       processed every time the completion menu is displayed.
+                       If set to 0 the entire buffer is processed without
+                       regard to timeout.
+                       By default this is set to 100 ms (good for scanning
+                       a file of about 6000 lines on M1 Macbook).
 
 For example, to disable the automatic placement of signs for the LSP
 diagnostic messages, you can add the following line to your .vimrc file: >