casouri / eldoc-box

childframe doc for eglot and anything that uses eldoc
360 stars 26 forks source link

scrolling support #29

Closed andreyorst closed 2 years ago

andreyorst commented 4 years ago

Sometimes eldoc is big. It would be nice to be able to scroll output. lsp-ui-doc has this feature, and also can be resized and focused with mouse.

image

This end paragraph was truncated: image

casouri commented 4 years ago

If you click the child frame (thus selecting it), can you scroll it? On mac I don't need to select the child frame to scroll, but I remember that Linux doesn't support this (or the other way around? I forgot)

As for resizing, you actually can resize it like a normal frame, but if the child frame has a thin border you have to place your cursor very accurately at the edge.

andreyorst commented 4 years ago

If I try to scroll or click frame disappears.

casouri commented 4 years ago

Even with emacs -q?

andreyorst commented 4 years ago

Yes

junyi-hou commented 4 years ago

I use the following set-transient-map tricks from lsp-ui to assign keymaps for scrolling

      (defconst gatsby:lsp-help-buffer-keymap
        (let ((map (make-sparse-keymap)))
          (suppress-keymap map t)
          (define-key map (kbd "J") #'gatsby:lsp-help-scroll-down)
          (define-key map (kbd "K") #'gatsby:lsp-help-scroll-up)
          (define-key map (kbd "C-u") #'gatsby:lsp-help-C-u)
          (define-key map (kbd "C-d") #'gatsby:lsp-help-C-d)
          (define-key map (kbd "C-g") #'gatsby:lsp-quit-help-frame)
          map)
        "Keymap in `gatsby:lsp-help-at-point'")

      (defvar-local gatsby:lsp-control-deactivate-fn nil
        "non-nil if current buffer can be controlled by `gatsby:lsp-help-buffer-keymap'.")

      (defun gatsby:lsp-quit-help-frame ()
        "Hide childframe, set `gatsby:lsp-control' to nil."
        (interactive)
        (when eldoc-box--frame
          (make-frame-invisible eldoc-box--frame t)
          (with-current-buffer eldoc-box--buffer
            (when-let ((fn gatsby:lsp-control-deactivate-fn))
              (setq-local gatsby:lsp-control-deactivate-fn nil)
              (funcall fn)))))

      (advice-add #'eldoc-box-quit-frame :override #'gatsby:lsp-quit-help-frame)

      (defun gatsby:lsp-help-scroll-up ()
        "Scroll up in `eldoc-box--frame'"
        (interactive)
        (with-current-buffer eldoc-box--buffer
          (when gatsby:lsp-control-deactivate-fn
            (with-selected-frame eldoc-box--frame
              (scroll-down 3)))))

      (defun gatsby:lsp-help-scroll-down ()
        "Scroll down in `eldoc-box--frame'"
        (interactive)
        (with-current-buffer eldoc-box--buffer
          (when gatsby:lsp-control-deactivate-fn
            (with-selected-frame eldoc-box--frame
              (scroll-up 3)))))

      (defun gatsby:lsp-help-C-d ()
        "C-d (`evil-scroll-down') for eldoc-box"
        (interactive)
        (with-current-buffer eldoc-box--buffer
          (when gatsby:lsp-control-deactivate-fn
            (with-selected-frame eldoc-box--frame
              (scroll-up (max 1 (/ (1- (window-height (selected-window))) 2)))))))

      (defun gatsby:lsp-help-C-u ()
        "C-u (`evil-scroll-up') for eldoc-box"
        (interactive)
        (with-current-buffer eldoc-box--buffer
          (when gatsby:lsp-control-deactivate-fn
            (with-selected-frame eldoc-box--frame
              (scroll-down (max 1 (/ (1- (window-height (selected-window))) 2)))))))

      (defun gatsby:lsp-help-at-point ()
        "display help in a childframe at point"
        (interactive)
        (unless eglot--managed-mode
          (user-error "`eglot' not enabled"))
        (unless (featurep 'eldoc-box)
          (user-error "`eldoc-box' not enabled"))
        (let ((eldoc-box-position-function
               #'eldoc-box--default-at-point-position-function)
              (eldoc-box-max-pixel-height
               (lambda ()
                 (- (nth 3 (window-absolute-body-pixel-edges))
                    (cdr (window-absolute-pixel-position))
                    40))))
          (eldoc-box--display
           (eglot--dbind ((Hover) contents range)
               (jsonrpc-request
                (eglot--current-server-or-lose)
                :textDocument/hover
                (eglot--TextDocumentPositionParams))
             (when (seq-empty-p contents) (eglot--error "No hover info here"))
             (eglot--hover-info contents range))))
        (with-current-buffer eldoc-box--buffer
          (setq-local gatsby:lsp-control-deactivate-fn
                      (set-transient-map gatsby:lsp-help-buffer-keymap
                                         t #'gatsby:lsp-quit-help-frame)))))