From aedb0d33de82595822a6fe56f40fdf608adc37c7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Sat, 5 Jan 2019 22:47:43 +0000 Subject: [PATCH] Show large docs in help buffer instead of echo are by default * eglot.el (eglot--managed-mode): Add and remove from eglot--eldoc-message (eglot--eldoc-hint, eglot--help-buffer): New helpers. (eglot-eldoc-extra-buffer) (eglot-auto-display-eldoc-extra-buffer): New defcustoms. (eglot--eldoc-message): New helper. (eglot-eldoc-function): Set eglot--eldoc-hint. (eglot-help-at-point): Use new helpers. (eglot-eldoc-extra-buffer-if-too-large): New predicate. GitHub-reference: per https://github.com/joaotavora/eglot/issues/198 --- lisp/progmodes/eglot.el | 79 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 71 insertions(+), 8 deletions(-) diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el index 98032b4a3e5..fb002b85a8e 100644 --- a/lisp/progmodes/eglot.el +++ b/lisp/progmodes/eglot.el @@ -1162,6 +1162,7 @@ and just return it. PROMPT shouldn't end with a question mark." (add-hook 'pre-command-hook 'eglot--pre-command-hook nil t) (eglot--setq-saving eldoc-documentation-function #'eglot-eldoc-function) (eglot--setq-saving flymake-diagnostic-functions '(eglot-flymake-backend t)) + (add-function :before-until (local 'eldoc-message-function) #'eglot--eldoc-message) (add-function :around (local 'imenu-create-index-function) #'eglot-imenu) (flymake-mode 1) (eldoc-mode 1)) @@ -1178,6 +1179,7 @@ and just return it. PROMPT shouldn't end with a question mark." (remove-hook 'change-major-mode-hook #'eglot--managed-mode-onoff t) (remove-hook 'post-self-insert-hook 'eglot--post-self-insert-hook t) (remove-hook 'pre-command-hook 'eglot--pre-command-hook t) + (remove-function (local 'eldoc-message-function) #'eglot--eldoc-message) (cl-loop for (var . saved-binding) in eglot--saved-bindings do (set (make-local-variable var) saved-binding)) (setq eglot--current-flymake-report-fn nil)))) @@ -2006,6 +2008,15 @@ is not active." (buffer-string)))) when moresigs concat "\n")) +(defvar eglot--eldoc-hint nil) + +(defvar eglot--help-buffer nil) + +(defun eglot--help-buffer () + (or (and (buffer-live-p eglot--help-buffer) + eglot--help-buffer) + (setq eglot--help-buffer (generate-new-buffer "*eglot-help*")))) + (defun eglot-help-at-point () "Request \"hover\" information for the thing at point." (interactive) @@ -2013,9 +2024,58 @@ is not active." (jsonrpc-request (eglot--current-server-or-lose) :textDocument/hover (eglot--TextDocumentPositionParams)) (when (seq-empty-p contents) (eglot--error "No hover info here")) - (let ((blurb (eglot--hover-info contents range))) - (with-help-window "*eglot help*" - (with-current-buffer standard-output (insert blurb)))))) + (let ((blurb (eglot--hover-info contents range)) + (sym (thing-at-point 'symbol))) + (with-current-buffer (eglot--help-buffer) + (with-help-window (current-buffer) + (rename-buffer (format "*eglot-help for %s*" sym)) + (with-current-buffer standard-output (insert blurb))))))) + +(defun eglot-eldoc-extra-buffer-if-too-large (string) + "Return non-nil if STRING won't fit in echo area. +Respects `max-mini-window-height' (which see)." + (let ((max-height + (cond ((floatp max-mini-window-height) (* (frame-height) + max-mini-window-height)) + ((integerp max-mini-window-height) max-mini-window-height) + (t 1)))) + (> (cl-count ?\n string) max-height))) + +(defcustom eglot-eldoc-extra-buffer + #'eglot-eldoc-extra-buffer-if-too-large + "If non-nil, put eldoc docstrings in separate `*eglot-help*' buffer. +If nil, use whatever `eldoc-message-function' decides (usually +the echo area). If t, use `*eglot-help; unconditionally. If a +function, it is called with the docstring to display and should a +boolean." + :type '(choice (const :tag "Never use `*eglot-help*'" nil) + (const :tag "Always use `*eglot-help*'" t) + (function :tag "Ask a function"))) + +(defcustom eglot-auto-display-eldoc-extra-buffer nil + "If non-nil, automatically display `*eglot-help*' buffer. +Buffer is displayed with `display-buffer', which obeys +`display-buffer-alist' & friends." + :type 'boolean) + +(defun eglot--eldoc-message (format &rest args) + (let ((string (apply #'format format args))) ;; FIXME: overworking? + (when (or (eq t eglot-eldoc-extra-buffer) + (funcall eglot-eldoc-extra-buffer string)) + (with-current-buffer (eglot--help-buffer) + (rename-buffer (format "*eglot-help for %s*" eglot--eldoc-hint)) + (let ((inhibit-read-only t)) + (erase-buffer) + (insert string) + (goto-char (point-min)) + (setq eldoc-last-message nil) + (if eglot-auto-display-eldoc-extra-buffer + (display-buffer (current-buffer)) + (unless (get-buffer-window (current-buffer)) + (eglot--message "Help for %s in in %s buffer" eglot--eldoc-hint + (buffer-name eglot--help-buffer)))) + (help-mode) + t))))) (defun eglot-eldoc-function () "EGLOT's `eldoc-documentation-function' function. @@ -2023,7 +2083,8 @@ If SKIP-SIGNATURE, don't try to send textDocument/signatureHelp." (let* ((buffer (current-buffer)) (server (eglot--current-server-or-lose)) (position-params (eglot--TextDocumentPositionParams)) - sig-showing) + sig-showing + (thing-at-point (thing-at-point 'symbol))) (cl-macrolet ((when-buffer-window (&body body) ; notice the exception when testing with `ert' `(when (or (get-buffer-window buffer) (ert-running-test)) @@ -2037,9 +2098,10 @@ If SKIP-SIGNATURE, don't try to send textDocument/signatureHelp." (when-buffer-window (when (cl-plusp (length signatures)) (setq sig-showing t) - (eldoc-message (eglot--sig-info signatures - activeSignature - activeParameter))))) + (let ((eglot--eldoc-hint thing-at-point)) + (eldoc-message (eglot--sig-info signatures + activeSignature + activeParameter)))))) :deferred :textDocument/signatureHelp)) (when (eglot--server-capable :hoverProvider) (jsonrpc-async-request @@ -2050,7 +2112,8 @@ If SKIP-SIGNATURE, don't try to send textDocument/signatureHelp." (when-let (info (and contents (eglot--hover-info contents range))) - (eldoc-message info))))) + (let ((eglot--eldoc-hint thing-at-point)) + (eldoc-message info)))))) :deferred :textDocument/hover)) (when (eglot--server-capable :documentHighlightProvider) (jsonrpc-async-request -- 2.39.2