From f601e9666d8b861712c09025711dc3a4261cb0ea Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Mon, 27 Feb 2023 14:54:53 +0000 Subject: [PATCH] Eglot: support multiple labels in same inlay hint Mainly the rust-analyzer LSP server uses this. There are still more things we could support, like tooltips and stuff. * lisp/progmodes/eglot.el (lsp-interface-alist): Add InlayHintLabelPart. (eglot--update-hints-1): Support multiple labels for same hint. --- lisp/progmodes/eglot.el | 40 +++++++++++++++++++++++++--------------- 1 file changed, 25 insertions(+), 15 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index ef758371c16..ffc9511469f 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -486,7 +486,8 @@ This can be useful when using docker to run a language server.") (WorkspaceEdit () (:changes :documentChanges)) (WorkspaceSymbol (:name :kind) (:containerName :location :data)) (InlayHint (:position :label) (:kind :textEdits :tooltip :paddingLeft - :paddingRight :data))) + :paddingRight :data)) + (InlayHintLabelPart (:value) (:tooltip :location :command))) "Alist (INTERFACE-NAME . INTERFACE) of known external LSP interfaces. INTERFACE-NAME is a symbol designated by the spec as @@ -3596,20 +3597,29 @@ If NOERROR, return predicate, else erroring function." (eglot--lambda ((InlayHint) position kind label paddingLeft paddingRight) (goto-char (eglot--lsp-position-to-point position)) (when (or (> (point) to) (< (point) from)) (cl-return)) - (let ((ov (make-overlay (point) (point))) - (left-pad (and paddingLeft (not (memq (char-before) '(32 9))))) - (right-pad (and paddingRight (not (memq (char-after) '(32 9))))) - (text (if (stringp label) - label (plist-get (elt label 0) :value)))) - (overlay-put ov 'before-string - (propertize - (concat (and left-pad " ") text (and right-pad " ")) - 'face (pcase kind - (1 'eglot-type-hint-face) - (2 'eglot-parameter-hint-face) - (_ 'eglot-inlay-hint-face)))) - (overlay-put ov 'eglot--inlay-hint t) - (overlay-put ov 'eglot--overlay t))))) + (let ((left-pad (and paddingLeft + (not (memq (char-before) '(32 9))) " ")) + (right-pad (and paddingRight + (not (memq (char-after) '(32 9))) " "))) + (cl-flet + ((do-it (text lpad rpad) + (let ((ov (make-overlay (point) (point)))) + (overlay-put ov 'before-string + (propertize + (concat lpad text rpad) + 'face (pcase kind + (1 'eglot-type-hint-face) + (2 'eglot-parameter-hint-face) + (_ 'eglot-inlay-hint-face)))) + (overlay-put ov 'eglot--inlay-hint t) + (overlay-put ov 'eglot--overlay t)))) + (if (stringp label) (do-it label left-pad right-pad) + (cl-loop + for i from 0 for ldetail across label + do (eglot--dbind ((InlayHintLabelPart) value) ldetail + (do-it value + (and (zerop i) left-pad) + (and (= i (1- (length label))) right-pad)))))))))) (jsonrpc-async-request (eglot--current-server-or-lose) :textDocument/inlayHint -- 2.39.5