var lsp_log_dir: string = '/tmp/'
# process the 'initialize' method reply from the LSP server
-def lsp#processInitializeReply(ftype: string, reply: dict<any>): void
+def LSPprocessInitializeReply(ftype: string, reply: dict<any>): void
if reply.result->len() <= 0
return
endif
exe 'inoremap <buffer> <silent> ' .. ch .. ' ' .. ch .. "<C-R>=lsp#showSignature()<CR>"
endfor
endif
+
+ # send a "initialized" notification to server
+ lsp#send_initialized(ftype)
enddef
# process the 'textDocument/definition' / 'textDocument/declaration' method
# replies from the LSP server
-def lsp#processDefDeclReply(reply: dict<any>): void
+def LSPprocessDefDeclReply(reply: dict<any>): void
if reply.result->len() == 0
echomsg "Error: definition is not found"
return
enddef
# process the 'textDocument/signatureHelp' reply from the LSP server
-def lsp#processSignaturehelpReply(reply: dict<any>): void
+def LSPprocessSignaturehelpReply(reply: dict<any>): void
var result: dict<any> = reply.result
if result.signatures->len() <= 0
echomsg 'No signature help available'
enddef
# process the 'textDocument/completion' reply from the LSP server
-def lsp#processCompletionReply(ftype: string, reply: dict<any>): void
+def LSPprocessCompletionReply(ftype: string, reply: dict<any>): void
var items: list<dict<any>> = reply.result.items
for item in items
lsp_servers[ftype].completePending = v:false
enddef
+# process the 'textDocument/hover' reply from the LSP server
+def LSPprocessHoverReply(ftype: string, reply: dict<any>): void
+ if type(reply.result) == v:t_none
+ return
+ endif
+
+ if reply.result.contents.kind == 'plaintext'
+ reply.result.contents.value->split("\n")->popup_atcursor({'moved': 'word'})
+ else
+ echomsg 'Error: Unsupported hover contents type (' .. reply.result.contents.kind .. ')'
+ endif
+enddef
+
# Process varous reply messages from the LSP server
def lsp#process_reply(ftype: string, req: dict<any>, reply: dict<any>): void
if req.method == 'initialize'
- lsp#processInitializeReply(ftype, reply)
+ LSPprocessInitializeReply(ftype, reply)
elseif req.method == 'textDocument/definition' || req.method == 'textDocument/declaration'
- lsp#processDefDeclReply(reply)
+ LSPprocessDefDeclReply(reply)
elseif req.method == 'textDocument/signatureHelp'
- lsp#processSignaturehelpReply(reply)
+ LSPprocessSignaturehelpReply(reply)
elseif req.method == 'textDocument/completion'
- lsp#processCompletionReply(ftype, reply)
+ LSPprocessCompletionReply(ftype, reply)
+ elseif req.method == 'textDocument/hover'
+ LSPprocessHoverReply(ftype, reply)
else
echomsg "Error: Unsupported reply received from LSP server: " .. string(reply)
endif
enddef
# Send a request message to LSP server
-def lsp#sendto_server(ftype: string, content: dict<any>): void
+def LSPsendto_server(ftype: string, content: dict<any>): void
var req_js: string = content->json_encode()
var msg = "Content-Length: " .. req_js->len() .. "\r\n\r\n"
var ch = lsp_servers[ftype].job->job_getchannel()
var initparams: dict<any> = {}
initparams.processId = getpid()
initparams.clientInfo = {'name': 'Vim', 'version': string(v:versionlong)}
- initparams.capabilities = {}
req.params->extend(initparams)
- lsp#sendto_server(ftype, req)
+ LSPsendto_server(ftype, req)
return 1
enddef
+# Send a "initialized" LSP notification
+def lsp#send_initialized(ftype: string)
+ var notif: dict<any> = lsp#create_notifmsg(ftype, 'initialized')
+ LSPsendto_server(ftype, notif)
+enddef
+
# Start a LSP server
def lsp#start_server(ftype: string): number
if lsp_servers[ftype].running
# Send a 'shutdown' request to the LSP server
def lsp#shutdown_server(ftype: string): void
var req = lsp#create_reqmsg(ftype, 'shutdown')
- lsp#sendto_server(ftype, req)
+ LSPsendto_server(ftype, req)
enddef
# Send a 'exit' notification to the LSP server
def lsp#exit_server(ftype: string): void
- var req: dict<any> = lsp#create_notifmsg(ftype, 'exit')
- lsp#sendto_server(ftype, req)
+ var notif: dict<any> = lsp#create_notifmsg(ftype, 'exit')
+ LSPsendto_server(ftype, notif)
enddef
# Stop a LSP server
tdi.text = getbufline(bnum, 1, '$')->join("\n") .. "\n"
notif.params->extend({'textDocument': tdi})
- lsp#sendto_server(ftype, notif)
+ LSPsendto_server(ftype, notif)
enddef
# Send a LSP "textDocument/didClose" notification
tdid.uri = 'file://' .. fname
notif.params->extend({'textDocument': tdid})
- lsp#sendto_server(ftype, notif)
+ LSPsendto_server(ftype, notif)
enddef
# Goto a definition using "textDocument/definition" LSP request
# interface Position
req.params->extend({'position': {'line': lnum, 'character': col}})
- lsp#sendto_server(ftype, req)
+ LSPsendto_server(ftype, req)
enddef
# Goto a declaration using "textDocument/declaration" LSP request
# interface Position
req.params->extend({'position': {'line': lnum, 'character': col}})
- lsp#sendto_server(ftype, req)
+ LSPsendto_server(ftype, req)
enddef
# Show the signature using "textDocument/signatureHelp" LSP method
# first send all the changes in the current buffer to the LSP server
listener_flush()
- var fname: string = expand('%:p')
var ftype: string = &filetype
- var lnum: number = line('.') - 1
- var col: number = col('.') - 1
-
- if fname == '' || ftype == ''
+ if ftype == ''
return ''
endif
+
if !lsp_servers->has_key(ftype)
echomsg 'Error: LSP server for "' .. ftype .. '" filetype is not found'
return ''
return ''
endif
+ var fname: string = expand('%:p')
+ if fname == ''
+ return ''
+ endif
+
+ var lnum: number = line('.') - 1
+ var col: number = col('.') - 1
+
var req = lsp#create_reqmsg(ftype, 'textDocument/signatureHelp')
# interface SignatureHelpParams
# interface TextDocumentPositionParams
# interface Position
req.params->extend({'position': {'line': lnum, 'character': col}})
- lsp#sendto_server(ftype, req)
+ LSPsendto_server(ftype, req)
return ''
enddef
changeset->add({'text': getbufline(bnum, 1, '$')->join("\n") .. "\n"})
notif.params->extend({'contentChanges': changeset})
- lsp#sendto_server(ftype, notif)
+ LSPsendto_server(ftype, notif)
enddef
# A new buffer is opened. If LSP is supported for this buffer, then add it
endif
lsp#textdoc_didopen(bnum, ftype)
+ # Display hover information
+ autocmd CursorHold <buffer> call LSPhover()
+
# add a listener to track changes to this buffer
listener_add(function('lsp#bufchange_listener'), bnum)
setbufvar(bnum, '&completefunc', 'lsp#completeFunc')
cwindow
enddef
-def lsp#getCompletion(): void
- var fname = expand('%:p')
+def LSPgetCompletion(): void
var ftype = &filetype
- var lnum = line('.') - 1
- var col = col('.') - 1
- if fname == '' || ftype == ''
+ if ftype == ''
return
endif
if !lsp_servers->has_key(ftype)
return
endif
+ var fname = expand('%:p')
+ if fname == ''
+ return
+ endif
+
+ var lnum = line('.') - 1
+ var col = col('.') - 1
+
var req = lsp#create_reqmsg(ftype, 'textDocument/completion')
# interface CompletionParams
# interface Position
req.params->extend({'position': {'line': lnum, 'character': col}})
- lsp#sendto_server(ftype, req)
+ LSPsendto_server(ftype, req)
enddef
def lsp#completeFunc(findstart: number, base: string): any
lsp_servers[ftype].completePending = v:true
lsp_servers[ftype].completeItems = []
# initiate a request to LSP server to get list of completions
- lsp#getCompletion()
+ LSPgetCompletion()
# locate the start of the word
var line = getline('.')
endif
enddef
+def LSPhover()
+ var ftype = &filetype
+ if ftype == ''
+ return
+ endif
+
+ if !lsp_servers->has_key(ftype)
+ echomsg 'Error: LSP server for "' .. ftype .. '" filetype is not found'
+ return
+ endif
+ if !lsp_servers[ftype].running
+ echomsg 'Error: LSP server for "' .. ftype .. '" filetype is not running'
+ return
+ endif
+
+ var fname = expand('%:p')
+ if fname == ''
+ return
+ endif
+ var lnum = line('.') - 1
+ var col = col('.') - 1
+
+ var req = lsp#create_reqmsg(ftype, 'textDocument/hover')
+ # interface HoverParams
+ # interface TextDocumentPositionParams
+ # interface TextDocumentIdentifier
+ req.params->extend({'textDocument': {'uri': 'file://' .. fname}})
+ # interface Position
+ req.params->extend({'position': {'line': lnum, 'character': col}})
+
+ LSPsendto_server(ftype, req)
+enddef
+
# vim: shiftwidth=2 sts=2 expandtab