5

In any buffer, try to eval-expression the expression (scroll-up 1) and then eval (goto-char 0). The window scrolls up, then point is moved to the beginning of the buffer. Now, try eval-ing (progn (scroll-up 1) (goto-char 0)). Here, point is not moved to the beginning of the buffer; the window scrolls up 1 line and point is moved to the middle of the screen.

Why is running (scroll-up 1) and then running (goto-char 0) any different from running (progn (scroll-up 1) (goto-char 0))?

jcarpenter2
  • 227
  • 1
  • 6
  • I would try using the `center` function with the `selected-window` (once point is where you want it) -- see the doc string for the arguments to control the desired position within the window. Alternatively, have a look at `set-window-point` ... If you are in another window/buffer, see the macro `with-selected-window`. – lawlist Apr 01 '18 at 08:44
  • You may also be interested in seeing whether `set-window-start` might be helpful ... – lawlist Apr 01 '18 at 08:54
  • Don't have answer for your question. However I am not very surprised that it doesn't work, since I don't know the internal of Emacs. Maybe you can try to force to redisplay: `(progn (scroll-up 1) (redisplay) (goto-char 1))`. – xuchunyang Apr 02 '18 at 01:55
  • @xuchunyang That code appears to give the desired effect. Still, even as you said, I still need to know why adding `(redisplay)` is necessary. I don't know the emacs internals either, but imho it flagrantly violates the principle of least surprise for `(progn (scroll-up 1) (goto-char 1))` not to be equivalent to running `(scroll-up 1)` followed by `(goto-char 1)`. The documentation `scroll-up` function does not mention that it a `(redisplay)` call should be required, for it to be used prior to certain invocations that move point. – jcarpenter2 Apr 03 '18 at 03:53

1 Answers1

0

Your save-excursion is working fine (i.e. point will be restored when that call exits), but with "point being along the top line of the window" you are scrolling that point out of the window; so at the end of the command loop Emacs will need to change point to a new value -- one which is visible in the window.

I don't see how you are expecting to get your "After (expected)" result, given that line 1 won't be in the window.

phils
  • 48,657
  • 3
  • 76
  • 115
  • Normally if point is moved to a location out of the window (e.g. by running `(goto-char 0)` when the top line of the file is not visible - or by running `previous-line` while point is on the top line of the screen), point will be moved to that location for the user and simultaneously the screen will be scrolled so that it's on-screen. Again my "Actual (expected)" behavior *does* happen if you step through either function in the debugger. It also happens if you run `(scroll-up 1)` followed by `(goto-char 0)` in eval-expression, but not if you run `(progn (scroll-up 1) (goto-char 0))`. – jcarpenter2 Apr 01 '18 at 20:46
  • What I don't understand is why there should be any difference running `(scroll-up 1)` followed by `(goto-char 0)` separately vs running them together as `(progn (scroll-up 1) (goto-char 0))`. – jcarpenter2 Apr 01 '18 at 20:48
  • Upon review you're right, I can't explain why the `goto-char` doesn't take effect in the `progn`. Note that zero isn't a character position; but that should still do what you intended. The *difference* between calling `eval-expression` once and calling it twice is that Emacs does things inbetween each command: the command loop happens twice instead of once. I don't know why calling the scroll command inhibits a `goto-char` which happened *later*, though. – phils Apr 02 '18 at 01:03
  • If I had to *guess*, I'd hazard that perhaps window scrolling defers certain activities until redisplay time, which might happen after other intervening actions -- but I really don't know. – phils Apr 02 '18 at 01:03