endfor
endif
- # map characters that trigger insert mode completion
- if caps->has_key('completionProvider')
+ if g:LSP_24x7_Complete && 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
+ lspserver.completionTriggerChars = triggers
endif
startcol = text->stridx(label)
endif
endif
- var popupID = text->popup_atcursor({})
+ var popupID = text->popup_atcursor({moved: 'any'})
prop_type_add('signature', {bufnr: popupID->winbufnr(), highlight: 'LineNr'})
if hllen > 0
prop_add(1, startcol + 1, {bufnr: popupID->winbufnr(), length: hllen, type: 'signature'})
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')
d.info = item.documentation.value
endif
endif
- lspserver.completeItems->add(d)
+ completeItems->add(d)
endfor
- lspserver.completePending = false
+ if g:LSP_24x7_Complete
+ if completeItems->empty()
+ # no matches
+ return
+ endif
+
+ if completeItems->len() == 1
+ && matchstr(getline('.'), completeItems[0].word .. '\>') != ''
+ # only one complete match. No need to show the completion popup
+ 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
+ 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)
+ else
+ lspserver.completeItems = completeItems
+ lspserver.completePending = false
+ endif
enddef
# process the 'textDocument/hover' reply from the LSP server
endif
lspserver.textdocDidOpen(bnr, ftype)
- # Display hover information
- autocmd CursorHold <buffer> call s:LspHover()
# file saved notification handler
autocmd BufWritePost <buffer> call s:lspSavedFile()
# 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')
+
+ # set options for insert mode completion
+ if g:LSP_24x7_Complete
+ setbufvar(bnr, '&completeopt', 'menuone,popup,noinsert,noselect')
+ setbufvar(bnr, '&completepopup', 'border:off')
+ # autocmd for 24x7 insert mode completion
+ autocmd TextChangedI <buffer> call lsp#complete()
+ # <Enter> in insert mode stops completion and inserts a <Enter>
+ inoremap <expr> <buffer> <CR> pumvisible() ? "\<C-Y>\<CR>" : "\<CR>"
+ else
+ setbufvar(bnr, '&omnifunc', 'lsp#omniFunc')
+ endif
+
setbufvar(bnr, '&balloonexpr', 'LspDiagExpr()')
exe 'autocmd InsertLeave <buffer=' .. bnr .. '> call lsp#leftInsertMode()'
WarnMsg('Error: No more diagnostics found')
enddef
+# Insert mode completion handler. Used when 24x7 completion is enabled
+# (default).
+def lsp#complete()
+ 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 lspserver->empty() || !lspserver.running || lspserver.caps->empty()
+ return
+ endif
+
+ # If the character before the cursor is not a keyword character or is not
+ # one of the LSP completion trigger characters, then do nothing.
+ 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
+
# omni complete handler
def lsp#omniFunc(findstart: number, base: string): any
var ftype: string = &filetype
# Display the hover message from the LSP server for the current cursor
# location
-def LspHover()
+def lsp#hover()
var ftype = &filetype
if ftype == ''
return
endif
var lspserver: dict<any> = s:lspGetServer(ftype)
- if lspserver->empty()
- return
- endif
- if !lspserver.running
+ if lspserver->empty() || !lspserver.running
return
endif
lspserver.nextID = 1
lspserver.requests = {}
lspserver.completePending = false
+ lspserver.completionTriggerChars = []
lspserver.workspaceFolders = [getcwd()]
var job = job_start(cmd, opts)
caps: {},
requests: {},
completePending: false,
+ completionTriggerChars: [],
diagsMap: {},
workspaceSymbolPopup: 0,
workspaceSymbolQuery: ''
Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
For Vim version 8.2.2342 and above
-Last change: Jan 20, 2021
+Last change: Jan 31, 2021
==============================================================================
*lsp-license*
==============================================================================
5. Commands *lsp-commands*
- |:LspShowServers|
+ *:LspShowServers*
:LspShowServers Displays the list of registered LSP servers and their
status. The LSP servers are registered using the
lsp#addServer() function. The output shows the Vim
file type, the corresponding LSP server status and the
path to the LSP server executable.
- |:LspGotoDefinition|
+ *:LspGotoDefinition*
:LspGotoDefinition Jumps to the definition of the symbol under the
cursor. If the file is already present in a window,
then jumps to that window. Otherwise, opens the file
Also the |``| mark is set to the position before the
jump.
- |:LspGotoDefinition|
+ *:LspGotoDefinition*
:LspGotoDeclaration Jumps to the declaration of the symbol under the
cursor. The behavior of this command is similar to the
|:LspGotoDefinition| command.
- |:LspGotoTypeDef|
+ *:LspGotoTypeDef*
:LspGotoTypeDef Jumps to the type definition of the symbol under the
cursor. The behavior of this command is similar to the
|:LspGotoDefinition| command. Note that not all the LSP
servers support this feature.
- |:LspGotoImpl|
+ *:LspGotoImpl*
:LspGotoImpl Jumps to the implementation of the symbol under the
cursor. The behavior of this command is similar to the
|:LspGotoDefinition| command. Note that not all the LSP
servers support this feature.
- |:LspShowSignature|
+ *:LspShowSignature*
:LspShowSignature Displays the signature of the symbol (e.g. a function
or method) before the cursor in a popup. The popup is
also automatically displayed in insert mode after
entering a symbol name followed by a separator (e.g. a
opening parenthesis).
- |:LspDiagShow|
+ *:LspDiagShow*
:LspDiagShow Creates a new location list with the diagnostics
messages (if any) from the LSP server for the current
file and opens the location list window. You can use
the Vim location list commands to browse the list.
- |:LspDiagFirst|
+ *:LspDiagFirst*
:LspDiagFirst Jumps to the location of the first diagnostic message
for the current file.
- |:LspDiagNext|
+ *:LspDiagNext*
:LspDiagNext Jumps to the location of the diagnostic message after
the current cursor position.
- |:LspDiagPrev|
+ *:LspDiagPrev*
:LspDiagPrev Jumps to the location of the diagnostic message before
the current cursor position.
- |:LspDiagCurrent|
+ *:LspDiagCurrent*
:LspDiagCurrent Displays the diagnostic message (if any) for the
current line.
- |:LspShowReferences|
+ *:LspShowReferences*
:LspShowReferences Creates a new location list with the list of locations
where the symbol under the cursor is referenced and
opens the location window.
- |:LspHighlight|
+ *:LspHighlight*
:LspHighlight Highlights all the matches for the symbol under
cursor. The text, read and write references to the
symbol are highlighted using Search, DiffChange and
DiffDelete highlight groups respectively.
- |:LspHighlightClear|
+ *:LspHighlightClear*
:LspHighlightClear Clears all the symbol matches highlighted by the
|:LspHighlight| command.
- |:LspOutline|
+ *:LspOutline*
:LspOutline Opens a vertically split window with the list of
symbols defined in the current file. The current
symbol is highlighted. The symbols are grouped by
the symbols in the new file. Folds are created in the
outline window for the various group of symbols.
- |:LspFormat|
+ *:LspFormat*
:LspFormat Format the current file using the LSP server.
:{range}LspFormat Format the specified range of lines in the current
file using the LSP server.
- |:LspCalledBy|
+ *:LspCalledBy*
:LspCalledBy Display the list of symbols called by the current
symbol. (NOT IMPLEMENTED YET).
- |:LspCalling|
+ *:LspCalling*
:LspCalling Display the list of symbols calling the current symbol
(NOT IMPLEMENTED YET).
- |:LspRename|
+ *:LspRename*
:LspRename Rename the current symbol. You will be prompted to
enter the new name for the symbol. You can press <Esc>
or enter an empty string in the prompt to cancel the
operation.
- |:LspCodeAction|
+ *:LspCodeAction*
:LspCodeAction Apply the code action supplied by the LSP server to
the diagnostic in the current line. This works only if
there is a diagnostic message for the current line.
prompted to select one of the actions supplied by the
LSP server.
- |:LspSymbolSearch|
+ *:LspSymbolSearch*
:LspSymbolSearch <sym> Perform a workspace wide search for the symbol <sym>.
A popup window is opened with the list of matching
symbols. You can enter a few characters to narrow
You can enter a new search pattern to do a workspace
wide symbol search.
- |:LspSelectionRange|
+ *:LspHover*
+:LspHover Show the documentation for the symbol under the cursor
+ in a popup window.
+
+ *:LspSelectionRange*
:LspSelectionRange Visually select the current symbol range.
- |:LspFold|
+ *:LspFold*
:LspFold Fold the current file.
- |:LspWorkspaceAddFolder|
+ *:LspWorkspaceAddFolder*
:LspWorkspaceAddFolder {folder}
Add a folder to the workspace
- |:LspWorkspaceRemoveFolder|
+ *:LspWorkspaceRemoveFolder*
:LspWorkspaceRemoveFolder {folder}
Remove a folder from the workspace
- |:LspWorkspaceListFolders|
+ *:LspWorkspaceListFolders*
: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.
+By default, in insert mode, the LSP plugin automatically displays the matches
+for the symbol under the cursor in an insert-completion popup menu. You can
+use the keys described in |popupmenu-keys| with this menu.
+
+To disable the auto-compeltion, you can set the LSP_24x7_Complete variable
+to v:false in your .vimrc file: >
+
+ let g:LSP_24x7_Complete=v:false
+<
+If this variable is set, then the LSP plugin doesn't automatically start
+completion in insert mode and instead supports omni-completion (|compl-omni|).
+It sets the 'omnifunc' option for the buffers which have a registered LSP
+server. To complete a symbol in insert mode manually, you can press CTRL-X
+CTRL-O to invoke completion using the items suggested by the LSP server.
==============================================================================
finish
endif
+" Perform completion in insert mode automatically. Otherwise use
+" omni-complete.
+if !exists('g:LSP_24x7_Complete')
+ let g:LSP_24x7_Complete = v:true
+endif
+
augroup LSPAutoCmds
au!
autocmd BufNewFile,BufReadPost *
command! -nargs=0 -bar LspRename call lsp#rename()
command! -nargs=0 -bar LspCodeAction call lsp#codeAction()
command! -nargs=? -bar LspSymbolSearch call lsp#symbolSearch(<q-args>)
+command! -nargs=0 -bar LspHover call lsp#hover()
command! -nargs=0 -bar LspSelectionRange call lsp#selectionRange()
command! -nargs=0 -bar LspFold call lsp#foldDocument()
command! -nargs=0 -bar LspWorkspaceListFolders call lsp#listWorkspaceFolders()
command! -nargs=1 -bar -complete=dir LspWorkspaceAddFolder call lsp#addWorkspaceFolder(<q-args>)
command! -nargs=1 -bar -complete=dir LspWorkspaceRemoveFolder call lsp#removeWorkspaceFolder(<q-args>)
+
+" vim: shiftwidth=2 softtabstop=2