From 0a2f143cae00db4488a56a5f9e27f0e3589a08ef Mon Sep 17 00:00:00 2001 From: Augusto Stoffel Date: Thu, 23 Feb 2023 08:55:58 +0100 Subject: [PATCH] Eglot: support positionEncoding LSP capability * lisp/progmodes/eglot.el(eglot-client-capabilities): Announce the new capability. (eglot-bytewise-column, eglot-move-to-bytewise-column): New functions. (eglot--managed-mode): Set 'eglot-current-column-function' and 'eglot-move-to-bytewise-column' appropriately. --- lisp/progmodes/eglot.el | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index b569c03e8c2..6b38d39c7b7 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -816,6 +816,9 @@ eglot-client-capabilities `(:valueSet [,@(mapcar #'car eglot--tag-faces)]))) + :general + (list + :positionEncodings ["utf-32" "utf-8" "utf-16"]) :experimental eglot--{}))) (cl-defgeneric eglot-workspace-folders (server) @@ -1441,6 +1444,11 @@ eglot--warn (defun eglot-current-column () (- (point) (line-beginning-position))) +(defun eglot-bytewise-column () + "Calculate current column using the LSP `utf-8' criterion." + (length (encode-coding-region (line-beginning-position) (point) + 'utf-8-unix t))) + (defvar eglot-current-column-function #'eglot-lsp-abiding-column "Function to calculate the current column. @@ -1505,6 +1513,18 @@ eglot-move-to-lsp-abiding-column (forward-char (/ (if (> diff 0) (1+ diff) (1- diff)) 2)) (end-of-buffer (cl-return eob-err)))))) +(defun eglot-move-to-bytewise-column (column) + "Move to COLUMN as computed using the LSP `utf-8' criterion." + (let* ((bol (line-beginning-position)) + (goal-byte (+ (position-bytes bol) column)) + (eol (line-end-position))) + (goto-char bol) + (while (and (< (position-bytes (point)) goal-byte) + (< (point) eol)) + (if (>= (char-after) #x3fff80) ; raw bytes take 2 bytes in the buffer + (setq goal-byte (1+ goal-byte))) + (forward-char 1)))) + (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" @@ -1758,6 +1778,14 @@ eglot--managed-mode :init-value nil :lighter nil :keymap eglot-mode-map (cond (eglot--managed-mode + (pcase (plist-get (eglot--capabilities (eglot-current-server)) + :positionEncoding) + ("utf-32" + (eglot--setq-saving eglot-current-column-function #'eglot-current-column) + (eglot--setq-saving eglot-move-to-column-function #'eglot-move-to-column)) + ("utf-8" + (eglot--setq-saving eglot-current-column-function #'eglot-bytewise-column) + (eglot--setq-saving eglot-move-to-column-function #'eglot-move-to-bytewise-column))) (add-hook 'after-change-functions 'eglot--after-change nil t) (add-hook 'before-change-functions 'eglot--before-change nil t) (add-hook 'kill-buffer-hook #'eglot--managed-mode-off nil t) -- 2.39.2