all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Felician Nemeth <felician.nemeth@gmail.com>
To: joaotavora@gmail.com
Cc: martin rudalics <rudalics@gmx.at>, Eli Zaretskii <eliz@gnu.org>,
	Alan Donovan <adonovan@google.com>,
	70193@debbugs.gnu.org
Subject: bug#70193: [PATCH] Re: bug#70193: Acknowledgement (eglot: RFE: recenter buffer upon showDocument request)
Date: Wed, 17 Apr 2024 11:15:25 +0200	[thread overview]
Message-ID: <87sezkcpua.fsf_-_@betli.tmit.bme.hu> (raw)
In-Reply-To: <CAPVWWDXd33XGG66YJuLn+Q0tfFkdvt2MXcDpe2TdNoaf1A3kpg@mail.gmail.com> (Alan Donovan's message of "Sat, 13 Apr 2024 12:36:41 -0400")

[-- Attachment #1: Type: text/plain, Size: 566 bytes --]

Hi João,

I've attached a patch fixing this issue.  It includes Martin's new
recenter-region.

This is the original report:

> In eglot 1.17, the LSP showDocument downcall opens the designated
> file, moves the cursor to the designated position, and raises the
> frame. One other thing it could do to make it easier to see where the
> cursor is would be to recenter the buffer.
> 
> The patch below is a minimal fix; the discussion at
> https://github.com/joaotavora/eglot/discussions/1382 suggests a couple
> of possible refinements.

Thanks.



[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Eglot-Recenter-buffer-upon-showDocument-request-bug-.patch --]
[-- Type: text/x-diff, Size: 5166 bytes --]

From 9496ee48c77f60c17387b4331911ba7ad5642c0e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Felici=C3=A1n=20N=C3=A9meth?= <felician.nemeth@gmail.com>
Date: Wed, 17 Apr 2024 10:47:03 +0200
Subject: [PATCH] Eglot: Recenter buffer upon showDocument request (bug#70193)

* lisp/progmodes/eglot.el (eglot--window-recenter-region): New
defun.
(eglot-handle-request window/showDocument): Try to show the whole
selection centered; in prog modes, try to show preceding comments
as well.

Co-authored-by: Martin Rudalics <rudalics@gmx.at>
---
 lisp/progmodes/eglot.el | 91 +++++++++++++++++++++++++++++++++++++++--
 1 file changed, 87 insertions(+), 4 deletions(-)

diff --git a/lisp/progmodes/eglot.el b/lisp/progmodes/eglot.el
index 5e4f7bba679..cbadd495b28 100644
--- a/lisp/progmodes/eglot.el
+++ b/lisp/progmodes/eglot.el
@@ -2488,6 +2488,76 @@ eglot-handle-request
   "Handle server request workspace/workspaceFolders."
   (eglot-workspace-folders server))
 
+(defun eglot--window-recenter-region (&optional from to window buffer)
+  "Center region and return window start position for recentered region.
+WINDOW specifies the window whose start position to return and defaults
+to the selected window.  BUFFER specifies the buffer supposed to contain
+the region and defaults to WINDOW's buffer. FROM and TO specify the
+beginning and end of the region in BUFFER and default to the active
+region or the entire text of BUFFER."
+  (let* ((window (or window (selected-window)))
+	 (buffer (or buffer (window-buffer window)))
+	 (from (or from
+		   (and (eq buffer (current-buffer))
+			(region-active-p)
+			(region-beginning))
+		   (with-current-buffer buffer
+		     (point-min))))
+	 (to (or to
+		 (and (eq buffer (current-buffer))
+		      (region-active-p)
+		      (region-end))
+		 (with-current-buffer buffer
+		   (point-max))))
+	 (body-width (window-body-width window t))
+	 (body-height (window-body-height window t))
+	 old-buffer old-point
+	 remainder height start prev)
+    ;; If WINDOW doesn't show BUFFER, save its buffer, start and point
+    ;; positions.
+    (unless (eq (window-buffer window) buffer)
+      (setq old-buffer (window-buffer window))
+      (setq old-point (window-point window))
+      (set-window-buffer window buffer))
+
+    ;; The amount of pixels by which the region can be scrolled down in
+    ;; the window.  Initially, half of the difference of the height of
+    ;; the window's body and that of the region.
+    (setq remainder
+	  (round
+	   (/ (- body-height
+		 (cdr (window-text-pixel-size
+		       window from to body-width body-height)))
+	      2.0)))
+
+    ;; Now move back and subtract the height of one line preceding the
+    ;; region until the remainder has been used.
+    (save-excursion
+      (goto-char from)
+      (setq start (pos-bol))
+      (while (and (not (bobp))
+		  (>= remainder 0)
+		  (setq prev (pos-bol 0))
+		  (setq height (cdr (window-text-pixel-size
+				   window prev start
+				   body-width body-height)))
+		  ;; At least half of the line should fit.
+		  (>= remainder (/ height 2.0)))
+	(setq remainder (- remainder height))
+	(setq start prev)
+	(goto-char start)))
+
+    ;; Restore WINDOW's old buffer, start and point.
+    (when old-buffer
+      (set-window-buffer window old-buffer)
+      (set-window-point window old-point)
+      (set-window-start window old-point))
+
+    (set-window-start window start)
+
+    ;; Return the new start position.
+    start))
+
 (cl-defmethod eglot-handle-request
   (_server (_method (eql window/showDocument)) &key
            uri external takeFocus selection)
@@ -2510,10 +2580,23 @@ eglot-handle-request
                  ((display-buffer (current-buffer))))
            (when selection
              (pcase-let ((`(,beg . ,end) (eglot-range-region selection)))
-               ;; FIXME: it is very naughty to use someone else's `--'
-               ;; function, but `xref--goto-char' happens to have
-               ;; exactly the semantics we want vis-a-vis widening.
-               (xref--goto-char beg)
+               (with-selected-window (get-buffer-window (current-buffer))
+                 ;; FIXME: it is very naughty to use someone else's `--'
+                 ;; function, but `xref--goto-char' happens to have
+                 ;; exactly the semantics we want vis-a-vis widening.
+                 (xref--goto-char end)
+                 (xref--goto-char beg)
+                 (eglot--window-recenter-region beg end)
+
+                 (when (derived-mode-p 'prog-mode)
+                   (let ((recentered-visible (pos-visible-in-window-p end))
+                         (recentered-start (window-start)))
+                     (reposition-window) ; Try to show preceding comments.
+                     (when (and recentered-visible
+                                (not (pos-visible-in-window-p end)))
+                       ;; reposition-window ruined visibility of selection.
+                       (set-window-start nil recentered-start)))))
+
                (pulse-momentary-highlight-region beg end 'highlight)))))))
      (t (setq success :json-false)))
     `(:success ,success)))
-- 
2.39.2


  reply	other threads:[~2024-04-17  9:15 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-04-04 13:17 bug#70193: eglot: RFE: recenter buffer upon showDocument request Alan Donovan via Bug reports for GNU Emacs, the Swiss army knife of text editors
     [not found] ` <handler.70193.B.171223666917509.ack@debbugs.gnu.org>
2024-04-04 13:32   ` bug#70193: Acknowledgement (eglot: RFE: recenter buffer upon showDocument request) Alan Donovan via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-04 14:43     ` Felician Nemeth
2024-04-05  9:07     ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-05 13:53       ` Felician Nemeth
2024-04-07  7:30         ` martin rudalics via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-13  8:08           ` Eli Zaretskii
2024-04-13  9:10             ` Felician Nemeth
2024-04-13 16:36               ` Alan Donovan via Bug reports for GNU Emacs, the Swiss army knife of text editors
2024-04-17  9:15                 ` Felician Nemeth [this message]
2024-04-17 12:13                   ` bug#70193: [PATCH] " João Távora
2024-04-23  7:43                     ` Felician Nemeth
2024-04-23  9:27                       ` João Távora
2024-04-24 16:37                         ` Juri Linkov
2024-04-24 20:14                           ` João Távora
2024-04-27 10:25                     ` Philip Kaludercic

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=87sezkcpua.fsf_-_@betli.tmit.bme.hu \
    --to=felician.nemeth@gmail.com \
    --cc=70193@debbugs.gnu.org \
    --cc=adonovan@google.com \
    --cc=eliz@gnu.org \
    --cc=joaotavora@gmail.com \
    --cc=rudalics@gmx.at \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.