The best a user can achieve -- without forcing a redisplay or without modifying the C-source code -- is use the window-end
function with the optional second argument set to t
in conjunction with the window-scroll-functions
hook that takes two arguments -- https://www.gnu.org/software/emacs/manual/html_node/elisp/Window-Hooks.html#Window-Hooks [NOTE: Forcing a redisplay may reveal to the naked eye (for a split second) an unfinished product -- e.g., perhaps the new overlays have not yet been removed/placed.]
CAVEAT: Beware that the window-scroll-functions
hook fires sometimes more than once during each command loop (while redisplay performs its job), and the first values for window-start
and window-end win t
are not always correct, and the last values are not always correct either -- e.g., when inserting/yanking, or when using goto
. [Fn 1.] When the window-scroll-functions
hook runs multiple times, the function attached to the hook can cause significant performance issues depending upon the complexity of said function. And, as mentioned, sometimes the user is simply out of luck -- i.e., correct values can never be obtained. Using pos-visible-in-window-p
can be helpful as a workaround to set up some checks to prevent the function attached to the hook from fully running its course if point
is not yet fully visible; and, a variable can be set up to test for whether the function has already fully run one time during that command loop (so that it doesn't keep running).
I have written a draft proof concept patch to the C-source code that I am using for my own personal setup to always get the correct window-start
and window-end
during redisplay; however, it may never make its way into the mainstream since I'm not a programmer and am the only person really motivated: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=22404 It is called the window-start-end-hook
-- but it's only available if a user wants to experiment with the draft patch and build Emacs from source. My draft patch works irrespective of window scrolling, e.g., it works when moving point within the visible window; it works when using goto
; it works when inserting/yanking; and, it works when scrolling. Anyone interested in developing that concept should please feel free to submit a post to feature request 22404.
See also these related threads:
How to update window-start without calling redisplay?
https://stackoverflow.com/questions/23923371/emacs-calculating-new-window-start-end-without-redisplay/24216247#24216247
NOTE: Debugging functions that run during redisplay may require using a feature called trace-redisplay
(after launching Emacs from the command line) that is available when building Emacs from source with options such as: ./configure --enable-checking='glyphs'
.
[Fn. 1.]: When working with Bug #22637, Eli Z. on the Emacs development team explained that the reason the window-scroll-functions
hook does not yield correct results for inserting/yanking or goto
is because it was never designed for those scenarios: "The reason window-scroll-functions aren't run in both of these test cases is that what happens there is not considered 'scrolling'. Scrolling is informally defined as either an explicit call to a function that scrolls the window, or a pseudo-scroll done by the display engine when it detects that some part of the window's previous display is still present, but in a different vertical position. Moving point to an arbitrary location is neither." https://debbugs.gnu.org/cgi/bugreport.cgi?bug=22637#35