branch: elpa/eldoc-mouse
commit c777c999736ba712ac61ce31c2c5c08ac19b3094
Author: huangfeiyu <[email protected]>
Commit: GitHub <[email protected]>
make eldoc-mouse generic.
Make eldoc-mouse not only for eglot managed buffers, but for any buffer
that using eldoc to show documentation, for example emacs-lisp-mode.
---
eldoc-mouse.el | 172 +++++++++++++++++++++++----------------------------------
1 file changed, 70 insertions(+), 102 deletions(-)
diff --git a/eldoc-mouse.el b/eldoc-mouse.el
index 2eadad2b939..970511a4777 100644
--- a/eldoc-mouse.el
+++ b/eldoc-mouse.el
@@ -28,10 +28,9 @@
;;; Commentary:
;; This package enhances eldoc' by displaying documentation in a child frame
-;; when the mouse hovers over a symbol in eglot'-managed buffers. It
integrates
-;; with posframe' for popup documentation and provides a debounced mouse hover
-;; mechanism to avoid spamming the LSP server. Enable it in prog-mode' buffers
-;; to show documentation for the symbol under the mouse cursor.
+;; when the mouse hovers over a symbol. It integrates with posframe' for
popup
+;; documentation. Enable it in buffers that you want to show documentation
using
+;; eldoc for the symbol under the mouse cursor.
;; To use, ensure posframe is installed, then add:
;; (require 'eldoc-mouse)
@@ -87,16 +86,20 @@ no limit, the popup may affect writing."
(defvar-local eldoc-mouse-last-symbol-bounds nil
"Bounds of the last symbol processed for eldoc.")
-(defvar-local eldoc-mouse-unsupress-posframe nil
- "Temporarily un-suppress the posframe.
-By default, posframe will not used by eldoc.")
-
(defvar-local eldoc-mouse--original-display-functions nil
"Store the original `eldoc-display-functions'.")
(defvar-local eldoc-mouse--doc-identifier "*^eldoc-mouse*^"
"The identifier used for distinguish the doc triggered by eldoc-mouse.")
+(defvar eldoc-mouse--eldoc-documentation-functions
+ '(eldoc-mouse--eglot-eldoc-documentation-function
+ eldoc-mouse--elisp-eldoc-documentation-function)
+ "The `eldoc-documentation-functions' for `eldoc-mouse-mode'.")
+
+(defvar-local eldoc-mouse--original-documentation-functions nil
+ "The original eldoc-documentation-fuctions.")
+
;;;###autoload
(define-minor-mode eldoc-mouse-mode
"Toggle the `eldoc-mouse-mode'."
@@ -112,44 +115,24 @@ By default, posframe will not used by eldoc.")
(interactive)
(eldoc-mouse--hide-posframe)
(when-let* ((symbol-bounds (bounds-of-thing-at-point 'symbol)))
- (cond
- (eldoc-mouse-mode
- (add-hook
- 'eldoc-documentation-functions #'eldoc-mouse-hover-eldoc-function
- nil t)
- (setq-local eldoc-mouse-last-symbol-bounds symbol-bounds)
- (setq-local eldoc-mouse-unsupress-posframe t)
-
- ;; Make sure eldoc always send the request to get doc.
- (setq eldoc--last-request-state nil)
-
- (eldoc-print-current-symbol-info)
- (remove-hook
- 'eldoc-documentation-functions #'eldoc-mouse-hover-eldoc-function
- t))
- (t
- (when (eglot-managed-p)
- (remove-hook
- 'eldoc-documentation-functions #'eglot-signature-eldoc-function
- t))
-
- (setq-local eldoc-mouse-last-symbol-bounds symbol-bounds)
+ (setq-local eldoc-mouse--original-documentation-functions
eldoc-documentation-functions)
+ (setq-local eldoc-documentation-functions nil)
+ (dolist (fun-sym eldoc-mouse--eldoc-documentation-functions)
+ (advice-add fun-sym :around #'eldoc-mouse--hover-edloc-function-advise)
+ (add-hook 'eldoc-documentation-functions (symbol-function fun-sym) nil
t))
+ (setq-local eldoc-mouse-last-symbol-bounds symbol-bounds)
+ (when (not eldoc-mouse-mode)
(unless eldoc-mouse--original-display-functions
- (setq-local eldoc-mouse--original-display-functions
- eldoc-display-functions))
+ (setq-local eldoc-mouse--original-display-functions
eldoc-display-functions))
(setq-local eldoc-display-functions
(append
- eldoc-display-functions '(eldoc-mouse-display-in-posframe)))
- (setq-local eldoc-mouse-unsupress-posframe t)
+ eldoc-display-functions
'(eldoc-mouse-display-in-posframe))))
+ (setq eldoc--last-request-state nil)
+ (eldoc-print-current-symbol-info)
+ (dolist (fun-sym eldoc-mouse--eldoc-documentation-functions)
+ (advice-remove fun-sym #'eldoc-mouse--hover-edloc-function-advise))
+ (setq-local eldoc-documentation-functions
eldoc-mouse--original-documentation-functions)))
- ;; Make sure eldoc always send the request to get doc.
- (setq eldoc--last-request-state nil)
-
- (eldoc-print-current-symbol-info)
- (when (eglot-managed-p)
- (add-hook 'eldoc-documentation-functions
#'eglot-signature-eldoc-function
- nil
- t))))))
(defun eldoc-mouse-enable ()
"Enable eldoc-mouse in buffers."
;; Enable mouse tracking.
@@ -160,17 +143,10 @@ By default, posframe will not used by eldoc.")
eldoc-display-functions '(eldoc-mouse-display-in-posframe)))
(local-set-key [mouse-movement] #'eldoc-mouse-doc-on-mouse)
- (when (eq major-mode 'emacs-lisp-mode)
- ;; (setq-local eldoc-documentation-functions nil)
- ;; (remove-hook 'eldoc-documentation-functions #'elisp-eldoc-var-docstring
t)
- ;; (remove-hook 'eldoc-documentation-functions #'elisp-eldoc-funcall t)
- (add-hook 'eldoc-documentation-functions
#'eldoc-mouse--elisp-eldoc-documentation-function nil t))
-
+ ;; Optimization for eglot managed buffers.
(when (eglot-managed-p)
-
;; Avoid unnecessary document of signatures that clutters the document.
- (remove-hook 'eldoc-documentation-functions
#'eglot-signature-eldoc-function
- t)
+ (remove-hook 'eldoc-documentation-functions
#'eglot-signature-eldoc-function t)
;; Avoid show document for the cursor.
(remove-hook 'eldoc-documentation-functions #'eglot-hover-eldoc-function t)
;; Enable highlight symbol under the cursor.
@@ -181,9 +157,7 @@ By default, posframe will not used by eldoc.")
;; See details:
;;
https://cgit.git.savannah.gnu.org/cgit/emacs.git/commit/?id=60166a419f601b413db86ddce186cc387e8ec269
(when (fboundp 'eglot--highlight-piggyback)
- (add-hook 'eldoc-documentation-functions #'eglot--highlight-piggyback
- nil
- t))))
+ (add-hook 'eldoc-documentation-functions #'eglot--highlight-piggyback
nil t))))
(defun eldoc-mouse-disable ()
"Disable eldoc-mouse in buffers."
@@ -191,28 +165,22 @@ By default, posframe will not used by eldoc.")
(setq-local eldoc-display-functions
eldoc-mouse--original-display-functions))
+ ;; Optimization for eglot managed buffers.
(when (eglot-managed-p)
(when (fboundp 'eglot--highlight-piggyback)
(remove-hook 'eldoc-documentation-functions #'eglot--highlight-piggyback
t))
(unless (memq #'eglot-signature-eldoc-function
eldoc-documentation-functions)
- (add-hook 'eldoc-documentation-functions #'eglot-signature-eldoc-function
- nil
- t))
+ (add-hook 'eldoc-documentation-functions
#'eglot-signature-eldoc-function nil t))
(unless (memq #'eglot-hover-eldoc-function eldoc-documentation-functions)
- (add-hook 'eldoc-documentation-functions #'eglot-hover-eldoc-function
- nil
- t)))
-
- (when (eq major-mode 'emacs-lisp-mode)
- (add-hook 'eldoc-documentation-functions
#'eldoc-mouse--elisp-eldoc-documentation-function nil t))
+ (add-hook 'eldoc-documentation-functions #'eglot-hover-eldoc-function
nil t)))
(when eldoc-mouse-mouse-timer
(cancel-timer eldoc-mouse-mouse-timer)
(setq eldoc-mouse-mouse-timer nil))
(eldoc-mouse--hide-posframe)
(local-unset-key [mouse-movement])
- (when (y-or-n-p "eldoc-mouse-mode has been turned off. Also disable
mouse-tracking (may impact other modes)?")
+ (when (y-or-n-p "eldoc-mouse-mode has been turned off. Also disable
mouse-tracking (may impact other modes)?")
(setq track-mouse nil)))
(defun eldoc-mouse--post-command-hook ()
@@ -241,13 +209,14 @@ POS is the buffer position under the mouse cursor."
(< pos (car eldoc-mouse-last-symbol-bounds))
(> pos (cdr eldoc-mouse-last-symbol-bounds))))
(eldoc-mouse--hide-posframe)
- (when (fboundp 'eglot--highlight-piggyback)
- (remove-hook 'eldoc-documentation-functions #'eglot--highlight-piggyback
- t))
(when eldoc-mouse-mouse-overlay
(delete-overlay eldoc-mouse-mouse-overlay))
(save-excursion
- ;; (add-hook 'eldoc-documentation-functions
#'eldoc-mouse-hover-eldoc-function nil t)
+ (setq-local eldoc-mouse--original-documentation-functions
eldoc-documentation-functions)
+ (setq-local eldoc-documentation-functions nil)
+ (dolist (fun-sym eldoc-mouse--eldoc-documentation-functions)
+ (advice-add fun-sym :around #'eldoc-mouse--hover-edloc-function-advise)
+ (add-hook 'eldoc-documentation-functions (symbol-function fun-sym) nil
t))
(goto-char pos)
(setq-local eldoc-mouse-last-symbol-bounds
(bounds-of-thing-at-point 'symbol))
@@ -257,21 +226,15 @@ POS is the buffer position under the mouse cursor."
(when (and eldoc-mouse-last-symbol-bounds
(not (eolp))
(not (nth 4 (syntax-ppss))))
- (setq-local eldoc-mouse-unsupress-posframe t)
- ;; (advice-add 'eglot-hover-eldoc-function :around
#'eldoc-mouse--hover-edloc-function-advise)
- (advice-add 'eldoc-mouse--elisp-eldoc-documentation-function :around
#'eldoc-mouse--hover-edloc-function-advise)
(eldoc-print-current-symbol-info)
- (advice-remove 'eldoc-mouse--elisp-eldoc-documentation-function
#'eldoc-mouse--hover-edloc-function-advise)
- ;; (advice-remove 'eglot-hover-eldoc-function
#'eldoc-mouse--hover-edloc-function-advise)
(setq-local eldoc-mouse-mouse-overlay
(make-overlay
(car eldoc-mouse-last-symbol-bounds)
(cdr eldoc-mouse-last-symbol-bounds)))
- (overlay-put eldoc-mouse-mouse-overlay 'face 'highlight))
- ;; (remove-hook 'eldoc-documentation-functions
#'eldoc-mouse-hover-eldoc-function t)
- ;; (when (fboundp 'eglot--highlight-piggyback)
- ;; (add-hook 'eldoc-documentation-functions
#'eglot--highlight-piggyback nil t))
- )))
+ (overlay-put eldoc-mouse-mouse-overlay 'face 'secondary-selection))
+ (dolist (fun-sym eldoc-mouse--eldoc-documentation-functions)
+ (advice-remove fun-sym #'eldoc-mouse--hover-edloc-function-advise))
+ (setq-local eldoc-documentation-functions
eldoc-mouse--original-documentation-functions))))
(defun eldoc-mouse--hide-posframe ()
"Hide the posframe."
@@ -283,7 +246,8 @@ POS is the buffer position under the mouse cursor."
(defun eldoc-mouse-doc-on-mouse (event)
"Show eldoc documentation when mouse hovers over EVENT."
(interactive "e")
- (let ((pos (posn-point (event-start event))))
+ (when eldoc-mouse-mode
+ (let ((pos (posn-point (event-start event))))
(when (and pos (number-or-marker-p pos))
;; Debounce to avoid spamming eglot.
(when eldoc-mouse-mouse-timer
@@ -291,21 +255,41 @@ POS is the buffer position under the mouse cursor."
(setq eldoc-mouse-mouse-timer
(run-with-idle-timer
eldoc-mouse-idle-time nil #'eldoc-mouse-show-doc-at
- pos)))))
+ pos))))))
-(defun eldoc-mouse-hover-eldoc-function (cb)
+(defun eldoc-mouse--eglot-eldoc-documentation-function (cb)
"Modify the `eglot-hover-eldoc-function'.
So it won't call `eglot--highlight-piggyback` with `CB`."
- (if (fboundp 'eglot--highlight-piggyback)
- (cl-letf (((symbol-function 'eglot--highlight-piggyback)
- (lambda (&rest _args) (message ""))))
+ (if (eglot-managed-p)
+ (if (fboundp 'eglot--highlight-piggyback)
+ (cl-letf (((symbol-function 'eglot--highlight-piggyback)
+ (lambda (&rest _args) (message ""))))
+ (eglot-hover-eldoc-function cb))
(eglot-hover-eldoc-function cb))
- (eglot-hover-eldoc-function cb)))
+ nil))
+
+(defun eldoc-mouse--elisp-eldoc-documentation-function (_cb)
+ "The `eldoc-documentation-functions' implementation for elisp."
+ (if (eq major-mode 'emacs-lisp-mode)
+ (let ((sym (symbol-at-point)))
+ (cond
+ ;; If the symbol is a function
+ ((and sym (fboundp sym))
+ (documentation sym))
+ ;; If the symbol is a variable
+ ((and sym (boundp sym))
+ (let ((doc (documentation-property sym 'variable-documentation)))
+ (if doc
+ doc
+ nil)))
+ ;; If no symbol or not a function/variable
+ (t nil)))
+ nil))
(defun eldoc-mouse--hover-edloc-function-advise (orig-fn fn)
"Wrap FN argument of ORIG-FN so that it append indentifier'."
(let ((result (funcall orig-fn
- (lambda (s @rest r)
+ (lambda (s &rest r)
(funcall fn (if (and s (not (string-empty-p (string-trim s))))
(concat s eldoc-mouse--doc-identifier)
s) r)))))
@@ -363,22 +347,6 @@ So it won't call `eglot--highlight-piggyback` with `CB`."
(add-hook 'post-command-hook #'eldoc-mouse--post-command-hook nil t)
(add-hook 'buffer-list-update-hook #'eldoc-mouse--change-buffer-hook nil t))
-(defun eldoc-mouse--elisp-eldoc-documentation-function (_cb)
- "The `eldoc-documentation-functions' implementation for elisp."
- (let ((sym (symbol-at-point)))
- (cond
- ;; If the symbol is a function
- ((and sym (fboundp sym))
- (documentation sym))
- ;; If the symbol is a variable
- ((and sym (boundp sym))
- (let ((doc (documentation-property sym 'variable-documentation)))
- (if doc
- doc
- nil)))
- ;; If no symbol or not a function/variable
- (t nil))))
-
(provide 'eldoc-mouse)
;; Local Variables: