]> Sergey Matveev's repositories - vim-lsp.git/commitdiff
Use the new Vim function to get/set cursor based on characters instead of bytes
authorYegappan Lakshmanan <yegappan@yahoo.com>
Sun, 17 Jan 2021 21:38:35 +0000 (13:38 -0800)
committerYegappan Lakshmanan <yegappan@yahoo.com>
Sun, 17 Jan 2021 21:38:35 +0000 (13:38 -0800)
README.md
autoload/handlers.vim
autoload/lsp.vim
autoload/lspserver.vim
autoload/util.vim
doc/lsp.txt
plugin/lsp.vim

index 75c98a92f8aa8192802b336650bf002d05a6df0d..10f661935860c17a91a0b4edd85d53d865df2338 100644 (file)
--- 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
 
index 53f265ef21dca1b1107b4f18b71824f3aff88b09..74b004534025d3f210e5e4c08b57bec42da37c69 100644 (file)
@@ -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<any>, req: dict<any>, reply: dict<any>
 
   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
@@ -65,7 +69,8 @@ def s:processDefDeclReply(lspserver: dict<any>, req: dict<any>, reply: dict<any>
   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<any>, req: dict<any>, reply: dict<a
                                                ->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})
@@ -286,9 +291,10 @@ def s:processDocHighlightReply(lspserver: dict<any>, req: dict<any>, 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<any>, req: dict<any>, reply: dict<an
   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]}
@@ -538,9 +519,9 @@ def s:applyTextEdits(bnr: number, text_edits: list<dict<any>>): 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<any>)
     # 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<any>, req: dict<any>, reply: di
   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
 
@@ -834,8 +819,7 @@ def s:processWorkspaceSymbolReply(lspserver: dict<any>, req: dict<any>, 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(
index 8408ed506cc6c382e5d2115af3a1b07cd837fb9c..f936a6ffb5ddf45508f911b3e324317898674cf7 100644 (file)
@@ -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<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
@@ -701,11 +705,12 @@ def s:addSymbolText(symbolTypeTable: dict<list<dict<any>>>,
     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<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}
@@ -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
index 90a0009f820825e2745611d602c079b376b198fd..fc344c7676aeabfd84b3020b710bc995aa92f658 100644 (file)
@@ -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<any>, chan: channel, msg: string): void
@@ -84,9 +92,9 @@ def s:initServer(lspserver: dict<any>)
     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<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
 
@@ -652,8 +659,8 @@ def s:codeAction(lspserver: dict<any>, fname_arg: string)
   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('.')
index 27c54eac6d389e848c711b793ac8b9dc1fa0f127..0b2bef2b44ce0b5353d8bfede2939884d997a729 100644 (file)
@@ -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>): 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
index 5658f3b60eeb056675fbff981639dfcb82d6c736..d280ba1873007960fa4fff43999a73b542dc6cb4 100644 (file)
@@ -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.
index 07978130054b0578d3e6283ebf854616aa2f9579..d1af460bb740de2922630f70a8f83f65fd3e407b 100644 (file)
@@ -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