branch: elpa/eldoc-mouse
commit eabeaa8567e766f959fa8c193a67734e7d12825e
Author: huangfeiyu <[email protected]>
Commit: GitHub <[email protected]>
Improve the doc display
remove the dependency of eldoc-box, use posframe for doc popup
---
eldoc-mouse.el | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 91 insertions(+), 4 deletions(-)
diff --git a/eldoc-mouse.el b/eldoc-mouse.el
index d55023bc74d..d33f8afc1d1 100644
--- a/eldoc-mouse.el
+++ b/eldoc-mouse.el
@@ -13,7 +13,7 @@
;; 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 eldoc-box' for popup documentation and provides a debounced mouse hover
+;; 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.
@@ -24,7 +24,7 @@
;;; Code:
(require 'eldoc)
-(require 'eldoc-box)
+(require 'posframe)
(require 'eglot)
(defgroup eldoc-mouse nil
@@ -38,6 +38,21 @@
:type 'number
:group 'eldoc-mouse)
+(defcustom eldoc-mouse-posframe-max-width 70
+ "The maximum number of charactersthe posframe may contain in each line."
+ :type 'number
+ :group 'eldoc-mouse)
+
+(defcustom eldoc-mouse-posframe-min-height 3
+ "The minimum number of lines posframe may contain."
+ :type 'number
+ :group 'eldoc-mouse)
+
+(defcustom eldoc-mouse-posframe-buffer-name "*doc-posframe-buffer*"
+ "The name of the hidden buffer used by posframe."
+ :type 'string
+ :group 'eldoc-mouse)
+
(defvar eldoc-mouse-mouse-timer nil
"Idle timer for mouse hover eldoc.")
@@ -49,9 +64,11 @@
POS is the buffer position under the mouse cursor."
(when (and pos
(number-or-marker-p pos)
+ (not (eldoc-mouse-is-mouse-hovering-posframe?
eldoc-mouse-posframe-buffer-name pos))
(or (eq eldoc-mouse-last-symbol-bounds nil)
(< pos (car eldoc-mouse-last-symbol-bounds))
(> pos (cdr eldoc-mouse-last-symbol-bounds))))
+ (posframe-hide eldoc-mouse-posframe-buffer-name)
(save-excursion
(add-hook 'eldoc-documentation-functions #'eglot-hover-eldoc-function
nil t)
(goto-char pos)
@@ -73,6 +90,7 @@ POS is the buffer position under the mouse cursor."
eldoc-mouse-idle-time nil #'eldoc-mouse-show-doc-at pos)))))
(defun eldoc-mouse-handle-eglot-hooks ()
+ (setq-local eldoc-display-functions (list #'eldoc-display-in-buffer
#'eldoc-mouse-display-in-posframe))
"remove the hooks that display doc on cursor hover, keep highlighting on
cursor."
;; Avoid unnecessary document of signatures that clutters the document.
(remove-hook 'eldoc-documentation-functions #'eglot-signature-eldoc-function
t)
@@ -85,10 +103,75 @@ POS is the buffer position under the mouse cursor."
(when (fboundp 'eglot--highlight-piggyback)
(add-hook 'eldoc-documentation-functions #'eglot--highlight-piggyback nil
t)))
+(defun eldoc-mouse-calc-posframe-width (max-width &optional frame)
+ "Compute a posframe width (in pixels)
+Return a number <pixels>.
+- The width won't exceed the width of the parent frame.
+- The function will respect the `max-width` to prevent exceeding it."
+ (let* ((frame (or frame (selected-frame)))
+ ;; Parent frame capacity in character cells:
+ (parent-cols (max 1 (- (frame-width frame) 1)))
+ (max-cols (or max-width most-positive-fixnum))
+ ;; Clamp to parent frame (in chars)
+ (final-cols (max 1 (min max-cols parent-cols)))
+ ;; Convert from character cells to pixels
+ (cw (+ 1 (frame-char-width frame)))) ;; character width in pixels
+ ;; Return the size in pixels
+ (* final-cols cw)))
+
+(defun eldoc-mouse-is-mouse-hovering-posframe? (posframe-name pos)
+ "Check if the mouse is hovering over the given posframe."
+ (let* ((posframe (get-buffer posframe-name)) ;; Get the posframe buffer
+ (frame (get-buffer-window posframe))
+ (posframe-params (and posframe (frame-parameters frame))))
+ (if posframe-params
+ (let* ((posframe-x (plist-get posframe-params :left))
+ (posframe-y (plist-get posframe-params :top))
+ (posframe-width (plist-get posframe-params :width))
+ (mouse-pos (window-absolute-pixel-position pos))
+ (posframe-height (plist-get posframe-params :height))) ;; Get
the mouse position
+ (and mouse-pos
+ posframe-x
+ posframe-y
+ posframe-width
+ posframe-height
+ (>= (car mouse-pos) posframe-x)
+ (< (car mouse-pos) (+ posframe-x posframe-width))
+ (>= (cdr mouse-pos) posframe-y)
+ (< (cdr mouse-pos) (+ posframe-y posframe-height))))
+ nil)))
+
+(defun eldoc-mouse-display-in-posframe (docs interactive)
+ "Display STRING in a posframe at the current mouse position."
+ (when docs
+ ;; output the document for *eldoc* buffer
+ (eldoc--format-doc-buffer docs)
+ (let* ((eldoc-buffer (get-buffer (car (seq-filter (lambda (buf)
(string-match-p ".*\\*eldoc.*\\*" (buffer-name buf))) (buffer-list)))))
+ (xy (window-absolute-pixel-position (car
eldoc-mouse-last-symbol-bounds)))
+ (frame (selected-frame))
+ (posframe-width-pixel (eldoc-mouse-calc-posframe-width
eldoc-mouse-posframe-max-width))
+ (posframe-xy (cons (min (car xy) (- (frame-pixel-width frame)
posframe-width-pixel))
+ (cdr xy))))
+ (when eldoc-buffer
+ (let ((text (with-current-buffer eldoc-buffer
+ (buffer-string)))
+ (border-color (face-foreground 'default)))
+ (when text
+ (posframe-show eldoc-mouse-posframe-buffer-name
+ :position posframe-xy
+ :width (/ posframe-width-pixel (frame-char-width
frame))
+ :min-height eldoc-mouse-posframe-min-height
+ :border-width 1
+ :border-color border-color
+ :string text))))
+
+ t))) ;; non-nil => suppress other display functions
+
+
(defun eldoc-mouse-setup ()
"Set up eldoc-mouse for the current buffer."
;; Enable eldoc-box hover mode
- (add-hook 'eglot-managed-mode-hook #'eldoc-box-hover-mode t)
+ ;; (add-hook 'eglot-managed-mode-hook #'eldoc-box-hover-mode t)
(add-hook 'eglot-managed-mode-hook #'eldoc-mouse-handle-eglot-hooks t)
;; Bind mouse movement to documentation display
(local-set-key [mouse-movement] #'eldoc-mouse-doc-on-mouse))
@@ -97,11 +180,15 @@ POS is the buffer position under the mouse cursor."
(defun eldoc-mouse-enable ()
"Enable eldoc-mouse in all `prog-mode' buffers."
(interactive)
+
+ ;; (setq eldoc-message-function #'eldoc-mouse-message-function)
;; Enable mouse tracking
(setq track-mouse t)
+
+ ;; (add-to-list 'eldoc-display-functions #'eldoc-mouse-display-in-posframe)
;; make sure the eldoc-mouse also enabled to the current buffer.
(when (eglot-managed-p)
- (eldoc-box-hover-mode)
+ ;; (eldoc-box-hover-mode)
(eldoc-mouse-handle-eglot-hooks)
(local-set-key [mouse-movement] #'eldoc-mouse-doc-on-mouse))
(add-hook 'prog-mode-hook #'eldoc-mouse-setup))