-Language Server Protocol (LSP) plugin for Vim9. You need Vim version 8.2.2241 or above to use this plugin.
+Language Server Protocol (LSP) plugin for Vim9. You need Vim version 8.2.2342 or above to use this plugin.
## Installation
# Refer to https://microsoft.github.io/language-server-protocol/specification
# for the Language Server Protocol (LSP) specificaiton.
-import {WarnMsg, ErrMsg, TraceLog, LspUriToFile} from './util.vim'
+import {WarnMsg,
+ ErrMsg,
+ TraceLog,
+ LspUriToFile,
+ GetLineByteFromPos} from './util.vim'
import {LspDiagsUpdated} from './buf.vim'
# process the 'initialize' method reply from the LSP server
var result: dict<any> = reply.result[0]
var file = LspUriToFile(result.uri)
- var wid = bufwinid(file)
+ var wid = file->bufwinid()
if wid != -1
win_gotoid(wid)
else
endif
# Set the previous cursor location mark
setpos("'`", getcurpos())
- cursor(result.range.start.line + 1, result.range.start.character + 1)
+ setcursorcharpos(result.range.start.line + 1,
+ result.range.start.character + 1)
redraw!
enddef
->trim("\t ", 1)
qflist->add({filename: fname,
lnum: loc.range.start.line + 1,
- col: loc.range.start.character + 1,
+ col: GetLineByteFromPos(bnr, loc.range.start) + 1,
text: text})
endfor
setqflist([], ' ', {title: 'Language Server', items: qflist})
# textual reference
propName = 'LspTextRef'
endif
- prop_add(docHL.range.start.line + 1, docHL.range.start.character + 1,
+ prop_add(docHL.range.start.line + 1,
+ GetLineByteFromPos(bnr, docHL.range.start) + 1,
{end_lnum: docHL.range.end.line + 1,
- end_col: docHL.range.end.character + 1,
+ end_col: GetLineByteFromPos(bnr, docHL.range.end) + 1,
bufnr: bnr,
type: propName})
endfor
lsp#updateOutlineWindow(fname, symbolTypeTable, symbolLineTable)
enddef
-# Returns the byte number of the specified line/col position. Returns a
-# zero-indexed column. 'pos' is LSP "interface position".
-def s:get_line_byte_from_position(bnr: number, pos: dict<number>): number
- # LSP's line and characters are 0-indexed
- # Vim's line and columns are 1-indexed
- var col: number = pos.character
- # When on the first character, we can ignore the difference between byte and
- # character
- if col > 0
- if !bnr->bufloaded()
- bnr->bufload()
- endif
-
- var ltext: list<string> = bnr->getbufline(pos.line + 1)
- if !ltext->empty()
- var bidx = ltext[0]->byteidx(col)
- if bidx != -1
- return bidx
- endif
- endif
- endif
-
- return col
-enddef
-
# sort the list of edit operations in the descending order of line and column
# numbers.
# 'a': {'A': [lnum, col], 'B': [lnum, col]}
for e in text_edits
# Adjust the start and end columns for multibyte characters
start_row = e.range.start.line
- start_col = s:get_line_byte_from_position(bnr, e.range.start)
+ start_col = GetLineByteFromPos(bnr, e.range.start)
end_row = e.range.end.line
- end_col = s:get_line_byte_from_position(bnr, e.range.end)
+ end_col = GetLineByteFromPos(bnr, e.range.end)
start_line = [e.range.start.line, start_line]->min()
finish_line = [e.range.end.line, finish_line]->max()
# interface TextEdit
s:applyTextEdits(bnr, changes)
endfor
+ # Restore the cursor to the location before the edit
save_cursor->setpos('.')
enddef
endif
var r: dict<dict<number>> = reply.result[0].range
+ var bnr: number = bufnr()
+ var start_col: number = GetLineByteFromPos(bnr, r.start) + 1
+ var end_col: number = GetLineByteFromPos(bnr, r.end)
- setpos("'<", [0, r.start.line + 1, r.start.character + 1, 0])
- setpos("'>", [0, r.end.line + 1, r.end.character, 0])
+ setcharpos("'<", [0, r.start.line + 1, start_col, 0])
+ setcharpos("'>", [0, r.end.line + 1, end_col, 0])
:normal gv
enddef
symbols->add({name: symName,
file: fileName,
- lnum: r.start.line + 1,
- col: r.start.character + 1})
+ pos: r.start})
endfor
symbols->setwinvar(lspserver.workspaceSymbolPopup, 'LspSymbolTable')
lspserver.workspaceSymbolPopup->popup_settext(
# Vim9 LSP client
import NewLspServer from './lspserver.vim'
-import {WarnMsg, ErrMsg, lsp_server_trace} from './util.vim'
+import {WarnMsg,
+ ErrMsg,
+ lsp_server_trace,
+ GetLineByteFromPos} from './util.vim'
-# Needs Vim 8.2.2082 and higher
-if v:version < 802 || !has('patch-8.2.2082')
+# Needs Vim 8.2.2342 and higher
+if v:version < 802 || !has('patch-8.2.2342')
finish
endif
text = diag.message->substitute("\n\\+", "\n", 'g')
qflist->add({'filename': fname,
'lnum': diag.range.start.line + 1,
- 'col': diag.range.start.character + 1,
+ 'col': GetLineByteFromPos(bnr, diag.range.start) + 1,
'text': text,
'type': s:lspDiagSevToQfType(diag.severity)})
endfor
for lnum in (which == 'next') ? sortedDiags : reverse(sortedDiags)
if (which == 'next' && lnum > curlnum)
|| (which == 'prev' && lnum < curlnum)
- call cursor(lnum, 1)
+ cursor(lnum, 1)
return
endif
endfor
# locate the start of the word
var line = getline('.')
- var start = col('.') - 1
+ var start = charcol('.') - 1
while start > 0 && line[start - 1] =~ '\k'
start -= 1
endwhile
var skipOutlineRefresh: bool = false
-def s:addSymbolText(symbolTypeTable: dict<list<dict<any>>>,
- pfx: string,
- text: list<string>,
- lnumMap: list<dict<any>>,
- children: bool)
+def s:addSymbolText(bnr: number,
+ symbolTypeTable: dict<list<dict<any>>>,
+ pfx: string,
+ text: list<string>,
+ lnumMap: list<dict<any>>,
+ children: bool)
var prefix: string = pfx .. ' '
for [symType, symbols] in items(symbolTypeTable)
if !children
for s in symbols
text->add(prefix .. s.name)
# remember the line number for the symbol
+ var start_col: number = GetLineByteFromPos(bnr, s.range.start) + 1
lnumMap->add({name: s.name, lnum: s.range.start.line + 1,
- col: s.range.start.character + 1})
+ col: start_col})
s.outlineLine = lnumMap->len()
if s->has_key('children') && !s.children->empty()
- s:addSymbolText(s.children, prefix, text, lnumMap, true)
+ s:addSymbolText(bnr, s.children, prefix, text, lnumMap, true)
endif
endfor
endfor
# First two lines in the buffer display comment information
var lnumMap: list<dict<any>> = [{}, {}]
var text: list<string> = []
- s:addSymbolText(symbolTypeTable, '', text, lnumMap, false)
+ s:addSymbolText(fname->bufnr(), symbolTypeTable, '', text, lnumMap, false)
append('$', text)
w:lspSymbols = {filename: fname, lnumTable: lnumMap,
symbolsByLine: symbolLineTable}
else
winList[0]->win_gotoid()
endif
- cursor(symTbl[result - 1].lnum, symTbl[result - 1].col)
+ setcursorcharpos(symTbl[result - 1].pos.line + 1,
+ symTbl[result - 1].pos.character + 1)
catch
# ignore exceptions
endtry
# Refer to https://microsoft.github.io/language-server-protocol/specification
# for the Language Server Protocol (LSP) specificaiton.
-import {ProcessReply, ProcessNotif, ProcessRequest, ProcessMessages} from './handlers.vim'
-import {WarnMsg, ErrMsg, ClearTraceLogs, TraceLog, LspUriToFile, LspFileToUri} from './util.vim'
+import {ProcessReply,
+ ProcessNotif,
+ ProcessRequest,
+ ProcessMessages} from './handlers.vim'
+import {WarnMsg,
+ ErrMsg,
+ ClearTraceLogs,
+ TraceLog,
+ LspUriToFile,
+ LspFileToUri} from './util.vim'
# LSP server standard output handler
def s:output_cb(lspserver: dict<any>, chan: channel, msg: string): void
textDocument: {
foldingRange: {lineFoldingOnly: v:true},
completion: {
- snippetSupport: v:true,
completionItem: {
documentationFormat: ['plaintext', 'markdown'],
+ snippetSupport: v:false
},
completionItemKind: {valueSet: range(1, 25)}
},
# line and not the byte index in the line.
def s:getLspPosition(): dict<number>
var lnum: number = line('.') - 1
- #var col: number = strchars(getline('.')[: col('.') - 1]) - 1
- var col: number = col('.') - 1
+ var col: number = charcol('.') - 1
return {line: lnum, character: col}
enddef
var bnr: number = bufnr(fname_arg)
req.params->extend({textDocument: {uri: LspFileToUri(fname)}})
var r: dict<dict<number>> = {
- start: {line: line('.') - 1, character: col('.') - 1},
- end: {line: line('.') - 1, character: col('.') - 1}}
+ start: {line: line('.') - 1, character: charcol('.') - 1},
+ end: {line: line('.') - 1, character: charcol('.') - 1}}
req.params->extend({range: r})
var diag: list<dict<any>> = []
var lnum = line('.')
return uri
enddef
+# Returns the byte number of the specified LSP position in buffer 'bnr'.
+# LSP's line and characters are 0-indexed.
+# Vim's line and columns are 1-indexed.
+# Returns a zero-indexed column.
+export def GetLineByteFromPos(bnr: number, pos: dict<number>): number
+ var col: number = pos.character
+ # When on the first character, we can ignore the difference between byte and
+ # character
+ if col > 0
+ # Need a loaded buffer to read the line and compute the offset
+ if !bnr->bufloaded()
+ bnr->bufload()
+ endif
+
+ var ltext: list<string> = bnr->getbufline(pos.line + 1)
+ if !ltext->empty()
+ var bidx = ltext[0]->byteidx(col)
+ if bidx != -1
+ return bidx
+ endif
+ endif
+ endif
+
+ return col
+enddef
+
# vim: shiftwidth=2 softtabstop=2
*lsp.txt* Language Server Protocol (LSP) Plugin for Vim9
Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
-For Vim version 8.2.2082 and above
-Last change: Jan 10, 2021
+For Vim version 8.2.2342 and above
+Last change: Jan 17, 2021
==============================================================================
*lsp-license*
https://microsoft.github.io/language-server-protocol/
https://langserver.org/
-This plugin needs Vim version 8.2.2082 and after. You will need a language
+This plugin needs Vim version 8.2.2342 and after. You will need a language
specific server in your system to use this plugin. Refer to the above pages
for a list of available language servers for the various programming
languages.
" LSP plugin for vim9
-" Needs Vim 8.2.2082 and higher
-if v:version < 802 || !has('patch-8.2.2082')
+" Needs Vim 8.2.2342 and higher
+if v:version < 802 || !has('patch-8.2.2342')
finish
endif