From: Yegappan Lakshmanan Date: Sun, 17 Jan 2021 21:38:35 +0000 (-0800) Subject: Use the new Vim function to get/set cursor based on characters instead of bytes X-Git-Url: http://www.git.stargrave.org/?a=commitdiff_plain;h=c5e41f20a1c91b7896637eb008c6cf2cb94e1c6b;p=vim-lsp.git Use the new Vim function to get/set cursor based on characters instead of bytes --- diff --git a/README.md b/README.md index 75c98a9..10f6619 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -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 diff --git a/autoload/handlers.vim b/autoload/handlers.vim index 53f265e..74b0045 100644 --- a/autoload/handlers.vim +++ b/autoload/handlers.vim @@ -4,7 +4,11 @@ vim9script # 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 @@ -57,7 +61,7 @@ def s:processDefDeclReply(lspserver: dict, req: dict, reply: dict var result: dict = reply.result[0] var file = LspUriToFile(result.uri) - var wid = bufwinid(file) + var wid = file->bufwinid() if wid != -1 win_gotoid(wid) else @@ -65,7 +69,8 @@ def s:processDefDeclReply(lspserver: dict, req: dict, reply: dict 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 @@ -254,7 +259,7 @@ def s:processReferencesReply(lspserver: dict, req: dict, reply: dicttrim("\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}) @@ -286,9 +291,10 @@ def s:processDocHighlightReply(lspserver: dict, req: dict, reply: dict # 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 @@ -399,31 +405,6 @@ def s:processDocSymbolReply(lspserver: dict, req: dict, reply: dict): 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 = 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]} @@ -538,9 +519,9 @@ def s:applyTextEdits(bnr: number, text_edits: list>): void 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() @@ -638,6 +619,7 @@ def s:applyWorkspaceEdit(workspaceEdit: dict) # interface TextEdit s:applyTextEdits(bnr, changes) endfor + # Restore the cursor to the location before the edit save_cursor->setpos('.') enddef @@ -737,9 +719,12 @@ def s:processSelectionRangeReply(lspserver: dict, req: dict, reply: di endif var r: dict> = 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 @@ -834,8 +819,7 @@ def s:processWorkspaceSymbolReply(lspserver: dict, req: dict, reply: d 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( diff --git a/autoload/lsp.vim b/autoload/lsp.vim index 8408ed5..f936a6f 100644 --- a/autoload/lsp.vim +++ b/autoload/lsp.vim @@ -3,10 +3,13 @@ vim9script # 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 @@ -412,7 +415,7 @@ def lsp#showDiagnostics(): void 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 @@ -494,7 +497,7 @@ def lsp#jumpToDiag(which: string): void 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 @@ -527,7 +530,7 @@ def lsp#completeFunc(findstart: number, base: string): any # 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 @@ -678,11 +681,12 @@ enddef var skipOutlineRefresh: bool = false -def s:addSymbolText(symbolTypeTable: dict>>, - pfx: string, - text: list, - lnumMap: list>, - children: bool) +def s:addSymbolText(bnr: number, + symbolTypeTable: dict>>, + pfx: string, + text: list, + lnumMap: list>, + children: bool) var prefix: string = pfx .. ' ' for [symType, symbols] in items(symbolTypeTable) if !children @@ -701,11 +705,12 @@ def s:addSymbolText(symbolTypeTable: dict>>, 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 @@ -743,7 +748,7 @@ def lsp#updateOutlineWindow(fname: string, # First two lines in the buffer display comment information var lnumMap: list> = [{}, {}] var text: list = [] - s:addSymbolText(symbolTypeTable, '', text, lnumMap, false) + s:addSymbolText(fname->bufnr(), symbolTypeTable, '', text, lnumMap, false) append('$', text) w:lspSymbols = {filename: fname, lnumTable: lnumMap, symbolsByLine: symbolLineTable} @@ -1112,7 +1117,8 @@ def s:jumpToWorkspaceSymbol(popupID: number, result: number): void 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 diff --git a/autoload/lspserver.vim b/autoload/lspserver.vim index 90a0009..fc344c7 100644 --- a/autoload/lspserver.vim +++ b/autoload/lspserver.vim @@ -4,8 +4,16 @@ vim9script # 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, chan: channel, msg: string): void @@ -84,9 +92,9 @@ def s:initServer(lspserver: dict) textDocument: { foldingRange: {lineFoldingOnly: v:true}, completion: { - snippetSupport: v:true, completionItem: { documentationFormat: ['plaintext', 'markdown'], + snippetSupport: v:false }, completionItemKind: {valueSet: range(1, 25)} }, @@ -326,8 +334,7 @@ enddef # line and not the byte index in the line. def s:getLspPosition(): dict 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 @@ -652,8 +659,8 @@ def s:codeAction(lspserver: dict, fname_arg: string) var bnr: number = bufnr(fname_arg) req.params->extend({textDocument: {uri: LspFileToUri(fname)}}) var r: dict> = { - 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> = [] var lnum = line('.') diff --git a/autoload/util.vim b/autoload/util.vim index 27c54ea..0b2bef2 100644 --- a/autoload/util.vim +++ b/autoload/util.vim @@ -89,4 +89,30 @@ export def LspFileToUri(fname: string): string 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 + 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 = 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 diff --git a/doc/lsp.txt b/doc/lsp.txt index 5658f3b..d280ba1 100644 --- a/doc/lsp.txt +++ b/doc/lsp.txt @@ -1,8 +1,8 @@ *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* @@ -35,7 +35,7 @@ Refer to the following pages for more information about LSP: 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. diff --git a/plugin/lsp.vim b/plugin/lsp.vim index 0797813..d1af460 100644 --- a/plugin/lsp.vim +++ b/plugin/lsp.vim @@ -1,7 +1,7 @@ " 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