From 3db93f0d70b43c876b41e2edfd7a89c97e594728 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Tue, 13 Nov 2018 22:08:16 +0000 Subject: [PATCH] Fix https://github.com/joaotavora/eglot/issues/125: add ability to report LSP-compliant columns * eglot.el (eglot-current-column-function): New variable. (eglot-lsp-abiding-column): New helper. (eglot--pos-to-lsp-position): Use eglot-current-column-function. (eglot-move-to-column-function): Tweak docstring. --- eglot.el | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/eglot.el b/eglot.el index d4a8b6f8a3..2c0b22e500 100644 --- a/eglot.el +++ b/eglot.el @@ -721,26 +721,42 @@ CONNECT-ARGS are passed as additional arguments to (let ((warning-minimum-level :error)) (display-warning 'eglot (apply #'format format args) :warning))) +(defvar eglot-current-column-function #'current-column + "Function to calculate the current column. + +This is the inverse operation of +`eglot-move-to-column-function' (which see). It is a function of +no arguments returning a column number. For buffers managed by +fully LSP-compliant servers, this should be set to +`eglot-lsp-abiding-column', and `current-column' (the default) +for all others.") + +(defun eglot-lsp-abiding-column () + "Calculate current COLUMN as defined by the LSP spec." + (/ (- (length (encode-coding-region (line-beginning-position) + (point) 'utf-16 t)) + 2) + 2)) + (defun eglot--pos-to-lsp-position (&optional pos) "Convert point POS to LSP position." (eglot--widening (list :line (1- (line-number-at-pos pos t)) ; F!@&#$CKING OFF-BY-ONE - :character (- (goto-char (or pos (point))) - (line-beginning-position))))) + :character (progn (when pos (goto-char pos)) + (funcall eglot-current-column-function))))) (defvar eglot-move-to-column-function #'move-to-column - "How to move to a column reported by the LSP server. + "Function 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. +`c'. However, many servers don't follow the spec this closely. -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.") +For buffers managed by fully LSP-compliant servers, this should +be set to `eglot-move-to-lsp-abiding-column', and +`move-to-column' (the default) for all others.") (defun eglot-move-to-lsp-abiding-column (column) "Move to COLUMN abiding by the LSP spec."