emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[elpa] externals/eglot 7b4ed97 33/45: Fix #124: add ability to move to L


From: João Távora
Subject: [elpa] externals/eglot 7b4ed97 33/45: Fix #124: add ability to move to LSP-precise columns
Date: Thu, 22 Nov 2018 19:15:32 -0500 (EST)

branch: externals/eglot
commit 7b4ed9736f8ab21adeee0205546d160313ab8b8f
Author: João Távora <address@hidden>
Commit: João Távora <address@hidden>

    Fix #124: add ability to move to LSP-precise columns
    
    Also close #125.
    
    Idea and much of design contributed by Michał Krzywkowski
    <address@hidden>
    
    This introduces the variable eglot-move-to-column-function.
    
    According to the standard, LSP column/character offsets are based
    on a count of UTF-16 code units, not actual visual columns.  So
    when LSP says position 3 of a line containing just \"aXbc\",
    where X is a multi-byte character, it actually means `b', not
    `c'.  This is what the function
    `eglot-move-to-lsp-abiding-column' does.
    
    However, many servers don't follow the spec this closely, and
    thus this variable should be set to `move-to-column' in buffers
    managed by those servers.
    
    * eglot.el (eglot-move-to-column-function): New variable.
    (eglot-move-to-lsp-abiding-column): New function.
    (eglot--lsp-position-to-point): Use eglot-move-to-column-function.
---
 eglot.el | 43 +++++++++++++++++++++++++++++++++++--------
 1 file changed, 35 insertions(+), 8 deletions(-)

diff --git a/eglot.el b/eglot.el
index 576d7f3..f7b9c86 100644
--- a/eglot.el
+++ b/eglot.el
@@ -728,16 +728,43 @@ CONNECT-ARGS are passed as additional arguments to
          :character (- (goto-char (or pos (point)))
                        (line-beginning-position)))))
 
+(defvar eglot-move-to-column-function #'move-to-column
+  "How to move to a column reported by the LSP server.
+
+According to the standard, LSP column/character offsets are based
+on a count of UTF-16 code units, not actual visual columns.  So
+when LSP says position 3 of a line containing just \"aXbc\",
+where X is a multi-byte character, it actually means `b', not
+`c'.  This is what the function
+`eglot-move-to-lsp-abiding-column' does.
+
+However, many servers don't follow the spec this closely, and
+thus this variable should be set to `move-to-column' in buffers
+managed by those servers.")
+
+(defun eglot-move-to-lsp-abiding-column (column)
+  "Move to COLUMN abiding by the LSP spec."
+  (cl-loop
+   initially (move-to-column column)
+   with lbp = (line-beginning-position)
+   for diff = (- column
+                 (/ (- (length (encode-coding-region lbp (point) 'utf-16 t))
+                       2)
+                    2))
+   until (zerop diff)
+   for offset = (max 1 (abs (/ diff 2)))
+   do (if (> diff 0) (forward-char offset) (backward-char offset))))
+
 (defun eglot--lsp-position-to-point (pos-plist &optional marker)
   "Convert LSP position POS-PLIST to Emacs point.
 If optional MARKER, return a marker instead"
-  (save-excursion (goto-char (point-min))
-                  (forward-line (min most-positive-fixnum
-                                     (plist-get pos-plist :line)))
-                  (forward-char (min (plist-get pos-plist :character)
-                                     (- (line-end-position)
-                                        (line-beginning-position))))
-                  (if marker (copy-marker (point-marker)) (point))))
+  (save-excursion
+    (goto-char (point-min))
+    (forward-line (min most-positive-fixnum
+                       (plist-get pos-plist :line)))
+    (unless (eobp) ;; if line was excessive leave point at eob
+      (funcall eglot-move-to-column-function (plist-get pos-plist :character)))
+    (if marker (copy-marker (point-marker)) (point))))
 
 (defun eglot--path-to-uri (path)
   "URIfy PATH."
@@ -1040,7 +1067,7 @@ Uses THING, FACE, DEFS and PREPEND."
                    (priority . ,(+ 50 i))
                    (keymap . ,(let ((map (make-sparse-keymap)))
                                 (define-key map [mouse-1]
-                                  (eglot--mouse-call 'eglot-code-actions))
+                                            (eglot--mouse-call 
'eglot-code-actions))
                                 map)))))
 
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]