From: João Távora Date: Tue, 11 Feb 2025 16:50:23 +0000 (+0000) Subject: Eglot: use Eldoc in eglot-hierarchy-mode X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=3f15053ccda4b9128df59f61021fca3c2370570e;p=emacs.git Eglot: use Eldoc in eglot-hierarchy-mode Use it to show details of the thing at point, like the full signature and the locus of the definition. * lisp/progmodes/eglot.el: Add optional arg MODE. (eglot--hierarchy-source-major-mode): New defvar. (eglot--hierarchy-1): Adjust. (eglot-hierarchy-mode): Set eldoc stuff. (eglot-hierarchy-center-on-node): Cosmetic fix. (eglot-hierarchy-detail-eldoc-function) (eglot-hierarchy-locus-eldoc-function): New eldoc functions. (cherry picked from commit 3fd0b802de20dc83b5d5236b6d458df73c9d4e77) --- diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index fd94e91828c..b5f3afa5d54 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1955,32 +1955,34 @@ Doubles as an indicator of snippet support." (unless (bound-and-true-p yas-minor-mode) (yas-minor-mode 1)) (apply #'yas-expand-snippet args))))) - (defun eglot--format-markup (markup) + (defun eglot--format-markup (markup &optional mode) "Format MARKUP according to LSP's spec. MARKUP is either an LSP MarkedString or MarkupContent object." - (let (string mode language) + (let (string render-mode language) (cond ((stringp markup) (setq string markup - mode 'gfm-view-mode)) + render-mode (or mode 'gfm-view-mode))) ((setq language (plist-get markup :language)) ;; Deprecated MarkedString (setq string (concat "```" language "\n" (plist-get markup :value) "\n```") - mode 'gfm-view-mode)) + render-mode (or mode 'gfm-view-mode))) (t ;; MarkupContent (setq string (plist-get markup :value) - mode (pcase (plist-get markup :kind) - ("markdown" 'gfm-view-mode) - ("plaintext" 'text-mode) - (_ major-mode))))) + render-mode + (or mode + (pcase (plist-get markup :kind) + ("markdown" 'gfm-view-mode) + ("plaintext" 'text-mode) + (_ major-mode)))))) (with-temp-buffer (setq-local markdown-fontify-code-blocks-natively t) (insert string) (let ((inhibit-message t) (message-log-max nil) match) - (ignore-errors (delay-mode-hooks (funcall mode))) + (ignore-errors (delay-mode-hooks (funcall render-mode))) (font-lock-ensure) (goto-char (point-min)) (let ((inhibit-read-only t)) @@ -3527,8 +3529,7 @@ for which LSP on-type-formatting should be requested." (ensure-resolved (get-text-property 0 'eglot--lsp-item proxy)) :detail))) (when (and (stringp detail) (not (string= detail ""))) - ;; Forces major-mode based fontification - (eglot--format-markup (list :value detail))))) + (eglot--format-markup detail major-mode)))) :company-doc-buffer (lambda (proxy) (let* ((resolved @@ -4530,6 +4531,7 @@ If NOERROR, return predicate, else erroring function." (defvar-local eglot--hierarchy-roots nil) (defvar-local eglot--hierarchy-specs nil) +(defvar-local eglot--hierarchy-source-major-mode nil) (defun eglot--hierarchy-children (node) (cl-flet ((get-them (method node) @@ -4601,6 +4603,7 @@ If NOERROR, return predicate, else erroring function." (defun eglot--hierarchy-1 (name provider preparer specs) (eglot-server-capable-or-lose provider) (let* ((server (eglot-current-server)) + (mode major-mode) (roots (jsonrpc-request server preparer @@ -4613,6 +4616,7 @@ If NOERROR, return predicate, else erroring function." eglot--hierarchy-roots roots eglot--hierarchy-specs specs eglot--cached-server server + eglot--hierarchy-source-major-mode mode buffer-read-only t revert-buffer-function (lambda (&rest _ignore) @@ -4650,16 +4654,40 @@ If NOERROR, return predicate, else erroring function." (define-derived-mode eglot-hierarchy-mode special-mode "Eglot special" "Eglot mode for viewing hierarchies. \\{eglot-hierarchy-mode-map}" - :interactive nil) + :interactive nil + (setq eldoc-documentation-strategy + #'eldoc-documentation-compose) + (add-hook 'eldoc-documentation-functions + #'eglot-hierarchy-detail-eldoc-function + nil t) + (add-hook 'eldoc-documentation-functions + #'eglot-hierarchy-locus-eldoc-function + t t)) (defun eglot-hierarchy-center-on-node () "Refresh hierarchy, centering on node at point." (interactive) (setq-local eglot--hierarchy-roots (list (get-text-property (point) - 'eglot--hierarchy-node))) + 'eglot--hierarchy-node))) (eglot--hierarchy-2)) +(defun eglot-hierarchy-detail-eldoc-function (_cb &rest _ignored) + (when-let* ((detail + (plist-get (get-text-property (point) 'eglot--hierarchy-node) + :detail))) + (eglot--format-markup detail eglot--hierarchy-source-major-mode))) + +(defun eglot-hierarchy-locus-eldoc-function (_cb &rest _ignored) + (let* ((node (get-text-property (point) 'eglot--hierarchy-node)) + (uri (plist-get node :uri)) + (loc (plist-get (plist-get node :range) :start))) + (and uri loc + ;; maybe use `file-relative-name'? + (format "%s:%s:%s" (eglot-uri-to-path uri) + (1+ (plist-get loc :line)) + (plist-get loc :character))))) + ;;; Hacks ;;;