From: Alan Mackenzie <acm@muc.de>
To: Anders Lindgren <andlind@gmail.com>
Cc: emacs-devel@gnu.org
Subject: Re: Scrolling and follow-mode
Date: Sun, 27 Apr 2014 11:52:15 +0000 [thread overview]
Message-ID: <20140427115215.GB3091@acm.acm> (raw)
In-Reply-To: <CABr8ebZCWmvHGgEWnzS4UBcWc5GpgqH2CwjMAkJLVJzLAODy=Q@mail.gmail.com>
Hi, Anders.
On Tue, Apr 22, 2014 at 10:20:46PM +0200, Anders Lindgren wrote:
> When it comes to the patch, it looks well written. I have only two comments:
> * The documentation says that `follow-fixed-window` is the window that must
> not be scrolled. However, in the code, it's only read once, as the
> condition to a `when`, so the actual value doesn't matter as long as it's
> non-nil. Wouldn't it better do document is a boolean?
Yes, I think so too. I've changed it to a boolean.
> * The code at (your) lines --- 1201,1222 ---- could be cleaner. It contains
> a `let*` that sets two variables, `dest` and `windows` and set a bunch
> others to a default nil value. The others are later set using a `setq`. I
> would suggest placing your code before the first assignment of `dest` and
> simply move the point, that way `dest` will get the value of the new point.
> Then use a new `let*` to set the others. Like the following (untested) code:
> (let ((windows (follow-all-followers win)))
> (when follow-fixed-window
> (follow-debug-message "fixed")
> (follow-redisplay windows win)
> (goto-char (follow-get-scrolled-point (point) windows))
> (setq follow-fixed-window nil))
> (let* ((dest (point))
> (win-start-end (progn
> (follow-update-window-start (car windows))
> (follow-windows-start-end windows)))
> (aligned (follow-windows-aligned-p win-start-end))
> (visible (follow-pos-visible dest win win-start-end))
> selected-window-up-to-date)
> (unless (and aligned visible)
> (setq follow-windows-start-end-cache nil))
I've incorporated this change. (In my own personal copy, I mean). It is
indeed neater.
However, things aren't as simple as I thought. In follow-scroll-up, if
point is at EOB, and at the top of the last window, (follow-scroll-up 1)
should scroll EOB into the previous window. Instead it throws an
'end-of-buffer exception.
I've fixed this by using follow-previous-window and trying scroll-up
again. However, the fix contains nested `condition-case's in a while
loop, and I'm not totally happy with it. It's too "clever", really. (I
also need to put this fix into follow-scroll-down for negative ARGs.)
Here is what the change to follow-scroll-up currently looks like:
@@ -467,9 +519,23 @@
(interactive "P")
(cond ((not follow-mode)
(scroll-up arg))
+ ((eq arg '-)
+ (follow-scroll-down))
(arg
- (save-excursion (scroll-up arg))
- (setq follow-internal-force-redisplay t))
+ (let ((opoint (point)) (owin (selected-window)))
+ (while
+ ;; If we are too near EOB, try scrolling the previous window.
+ (condition-case nil (progn (scroll-up arg) nil)
+ (end-of-buffer
+ (condition-case nil (progn (follow-previous-window) t)
+ (error
+ (select-window owin)
+ (goto-char opoint)
+ (signal 'end-of-buffer nil))))))
+ (unless (and scroll-preserve-screen-position
+ (get this-command 'scroll-command))
+ (goto-char opoint))
+ (setq follow-fixed-window t)))
(t
(let* ((windows (follow-all-followers))
(end (window-end (car (reverse windows)))))
#########################################################################
As a matter of interest, I mainly use a Linux tty for Emacs, and here
there is never a partially visible line at the bottom of the window. I
think in a GUI environment, there almost always is. While solving the
above issue, I stumbled over something in follow-calc-win-end: the flag
END-OF-BUFFER becomes t when EOB is at (window-end win), which is one
line beyond the end of the window (in a tty). I think the flag is meant
to mean "EOB is fully visible in WIN"; it is commented thus somewhere
else in the file. I've changed follow-calc-win-end as follows:
@@ -766,15 +842,16 @@
Return (END-POS END-OF-BUFFER).
Actually, the position returned is the start of the line after
-the last fully-visible line in WIN. If WIN is nil, the selected
-window is used."
+the last fully-visible line in WIN. END-OF-BUFFER is t when EOB
+is fully-visible in WIN. If WIN is nil, the selected window is
+used."
(let* ((win (or win (selected-window)))
(edges (window-inside-pixel-edges win))
(ht (- (nth 3 edges) (nth 1 edges)))
(last-line-pos (posn-point (posn-at-x-y 0 (1- ht) win))))
(if (pos-visible-in-window-p last-line-pos win)
(let ((end (window-end win t)))
- (list end (= end (point-max))))
+ (list end (pos-visible-in-window-p (point-max) win)))
(list last-line-pos nil))))
(defun follow-calc-win-start (windows pos win)
.
#########################################################################
With 3 follow windows, and the last few lines of text filling the middle
window, with just EOB in the right hand window, I encountered this
problem: put point at the end of the middle window (i.e. one character
before EOB) and do C-f. Point moves into the RH window, but the middle
and left windows scroll up 2 lines.
I tracked this down to follow-estimate-first-window-start (called from
follow-redisplay) which decrements the height of the current window
whilst moving vertically over it. In the above case, this left point two
lines too low, causing the unwanted scrolling.
So I patched the -1 out of the function, and it works, at least on the
tty. In the GUI, it is still scrolling 1 line up. I'll try and track
down what's causing this.
Here is the change I've made to follow-estimate-first-window-start:
@@ -1008,7 +1085,7 @@
(goto-char start)
(vertical-motion 0 win)
(dolist (w windows-before)
- (vertical-motion (- 1 (window-text-height w)) w))
+ (vertical-motion (- (window-text-height w)) w))
(point))))
> Again, thanks!
> Sincerely,
> Anders Lindgren
--
Alan Mackenzie (Nuremberg, Germany).
prev parent reply other threads:[~2014-04-27 11:52 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-04-21 16:17 Scrolling and follow-mode Alan Mackenzie
2014-04-22 20:20 ` Anders Lindgren
2014-04-27 11:52 ` Alan Mackenzie [this message]
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=20140427115215.GB3091@acm.acm \
--to=acm@muc.de \
--cc=andlind@gmail.com \
--cc=emacs-devel@gnu.org \
/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.