Q: How do I find the visual line number of point (so that I can restore it after an operation)?
By “visual line number”, I'm referring to the number N
of lines
between the top of the window (or the screen) and the cursor, not
the top of the buffer.
At first I thought I could calculate N
with the following snippet:
(- (line-number-at (point))
(line-number-at (window-start)))
However, to complicate things, I have sections of the buffer which are invisible.
So the snippet above usually returns values much larger than N
.
Context:
I need to perform an operation that essentially erases the entire
buffer and writes it again, but I want it to be mostly invisible to
the user.
Since the buffer contents are created anew, save-excursion
doesn't
help in this situation. Still, I manage to preserve point position by
saving it as a number, instead of a marker.
(let ((point (point)))
(recreate-buffer)
(goto-char point))
Q (alternative wording): Is there a similar method I can use to preserve the visual height of the cursor?
By that, I mean that if the cursor is initially on the N
th visible line of the screen, the window should be scrolled after the operation so that this remains true.
(set-window-start (selected-window) my-stored-window-start-pos)
and use the same point that you previously stored -- i.e.,(let ((my-stored-window-start-pos (window-start))) . . .)
forward-line
with test to see if its visible, and skip without counting if its invisible -- Goto predetermined window-start and thenfoward-line
x number of visible lines. X number of visible lines is equal to your proposed test above before erasing the buffer.next-line
, IIRC forward-line would count invisible lines.N
) andset-window-start
at previously recorded position. Then goto that window start and commence:(let ((count 0)) (catch 'done (while t (forward-line 1) (unless (invisible-p (point-at-bol)) (setq count (1+ count))) (when (= count N) (throw 'done nil)))))