4

While debugging swiper I've encountered a situation when the point is changed inside with-selected-window, but window-start isn't updated.

This can be annoying, because I need the up-to-date window bounds to update the overlays. From the doc, I've read that window-start can be updated with redisplay, and it is indeed updated, but calling redisplay after each key results in uncomfortable screen blinking and tearing.

Is there a way around it, i.e. update window-start like redisplay does it, but don't actually redisplay to avoid blinking?

Drew
  • 75,699
  • 9
  • 109
  • 225
abo-abo
  • 13,943
  • 1
  • 29
  • 43
  • 1
    Welcome to the beginning of your `redisplay` journey for `window-start` and `window-end` -- here is a link to a thread that launched the beginning of my own journey entitled **calculating new window-start/end without redisplay**: http://stackoverflow.com/a/24216247/2112489 Here is a link to the limited documentation on the `window-scroll-functions` hook: http://www.gnu.org/software/emacs/manual/html_node/elisp/Window-Hooks.html Here is a link to a minor mode example for implementing the above-concepts -- **character counting in visible window**: http://stackoverflow.com/a/24727864/2112489 – lawlist Apr 18 '15 at 17:12
  • I don't think it applies in this case. I need a new `window-end` *right now*, not later. That can't be solved by subscribing to stuff like post-command-hook or whatever. What's the point of subscribing if the info that I need right now isn't ready yet? – abo-abo Apr 18 '15 at 17:39
  • If you can't get it by using the optional `t` for `window-end WIN FORCE`, or if you can't get it by using the `window-scroll-functions` hook, then you are probably out of luck. – lawlist Apr 18 '15 at 18:00
  • Hence the question. – abo-abo Apr 18 '15 at 18:01
  • If you are having trouble getting the new `window-end`, then it is because `point` has moved outside of the prior visible window area. If point moves beyond the prior visible window area, then the `window-scroll-functions` hook fires *at least* one time -- that hook / function gives you the ability to obtain the value you seek provided that you are using `(window-end WIN FORCE)`. There is a complexity when point is partially visible, and a complexity when the `window-scroll-functions` hook fires more than one time, but that is a few steps ahead of where you are now. – lawlist Apr 18 '15 at 18:04
  • You don't have to call `redisplay-windows` after each command, only when the point is outside the old window area. I've done similar things in `follow-mode` (see `follow-adjust-window`). (Admittedly, the package was written 20 years ago so it might not reflect the state of the art.) – Lindydancer Apr 18 '15 at 20:13

1 Answers1

2

See also Emacs bug tracker feature request #22404 (which has not yet been implemented, but the mailing archive contains a rough draft rudimentary patch that creates a new hook for this specific issue): https://debbugs.gnu.org/cgi/bugreport.cgi?bug=22404


Whenever point moves outside of the visible window, the window-scroll-functions hook is triggered -- at the very least one (1) time -- before the screen updates visually. The window-scroll-functions hook is one of the last hooks available to the user via elisp from which to obtain the new values for window-start and window-end before a visual redisplay occurs. It is necessary to use the optional second argument in window-end -- i.e., t for force.

The function abo-abo-wsf-fn when attached to the window-scroll-functions hook will generate the new values for window-start and window-end prior to visual redisplay. The hook is using a buffer-local argument.

(defun abo-abo-wsf-fn (win _start)
"A function attached to the `window-scroll-functions` hook."
  (when
      (and
        (window-live-p (get-buffer-window (current-buffer)))
        (not (minibufferp)))
    (let* (
        (selected-window (selected-window))
        (window-start (window-start selected-window))
        (window-end (window-end selected-window t)) )
      (message "window-start: %s | window-end: %s" window-start window-end) )))

(add-hook 'window-scroll-functions 'abo-abo-wsf-fn nil t)

COMPLEXITIES:  The above-example is not designed to deal with the complexities of a point being partially visible, or situations when the window-scroll-functions hook is triggered more than one time per command loop. The links in the comments underneath the question of the original poster deal with those complexities. The original poster has not requested specific assistance in relation to those issues; however, so they are excluded from this limited example.

lawlist
  • 18,826
  • 5
  • 37
  • 118
  • This doesn't work. Nor would it make any sense if it did. If the window bounds can be updated through a hook, why aren't `window-start` and `window-end` simply subscribed to that hook? I solved my problem by assuming that window-start=point-window-height, and window-end=point+window-height. Not too efficient, but it works. – abo-abo Apr 19 '15 at 11:20
  • I respectfully disagree and need to leave this answer for future forum searchers, because it is not just **an answer**, it is **THE ANSWER!** Unfortunately, I may not have explained it as well as I could have and that is the reason it does not work for you. If I can come up with a better explanation of how and why this works, I will update the answer in the future. I am sorry that it did not help you; however, it will most definitely help others in the future. – lawlist Apr 19 '15 at 15:33
  • I can believe that `window-scroll-functions` will be called at some point. But I don't want to have a callback-calling callback for such a simple thing as having an up-to-date window-start. – abo-abo Apr 19 '15 at 15:39
  • The last link of the first comment to the original question is an example of a minor mode that places overlays on just the visible portions of the window, no matter how long the buffer is. The overlay placement functions are launched from a function akin to the `abo-abo-wsf-fn`, because that is the correct method to obtain the `window-start` and `window-end` that will exist when redisplay finishes and the screen updates. When the screen finally refreshes, the overlays are exactly between the new `window-start` and new `window-end` -- however, the user never sees a blink or naked buffer. – lawlist Apr 19 '15 at 15:49
  • I get that. But can you see how lame this is? To have an actual minor mode just for tracing `window-start`, which obviously is recomputed in the Emacs innards. If line A through line Z are displayed at any moment, there's a way to know what they are at any moment in the C code. Otherwise, how would the code know where from to take the characters? Getting `window-start` and `window-end` from those is elementary. – abo-abo Apr 19 '15 at 15:57
  • Unfortunately, Emacs presently only gives us (the end user) one (1) `elisp` tool to accurately obtain these new values for `window-start` and `window-end` before the screen visibly updates -- i.e., the `window-scroll-functions` hook. I wish there were a better way, but sadly there is not. – lawlist Apr 19 '15 at 16:01
  • Well, the devs actually read these questions. I'm hoping either for a quick fix, or maybe some help in implementing the proper thing. – abo-abo Apr 19 '15 at 16:04
  • 2
    Here is the link to the bug-report that I launched at the beginning of my quest to better understand how `window-start` and `window-end` are calculated before redisplay finishes. Eli and Stefan probably explain it much better than I can: http://lists.gnu.org/archive/html/bug-gnu-emacs/2014-06/msg00102.html – lawlist Apr 19 '15 at 16:06
  • @abo-abo -- in the event you are still interested in this issue, I've written a new draft prototype hook that may not ever get incorporated into the master branch -- however, some of the Emacs development team is examining the issue and there is talk of perhaps some type of a new hook to take advantage of the correct values of `window-start` and `window-end`. It is feature request 22404: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=22404 Also, please keep in mind that I'm not a programmer and just started acquiring some C programming basics a few days ago . . . e.g., if, if else, etc. :) – lawlist Feb 01 '16 at 03:50