1

I have a buffer which is updated periodically using run-at-time, and in order to maintain the point in each window I use set-window-point, but I find that in sometimes when something is interrupted and an update happens in between, the window point is not reset. For example, take:

(defun example ()
  (interactive)
  (let* ((buf (get-buffer-create "*Example*"))
         (w-points (mapcar (lambda (win)
                             `(,win . ,(window-point win)))
                           (get-buffer-window-list buf))))
    (with-current-buffer buf
      (let ((buf-point (point)))
        (erase-buffer)
        (insert "line1\nline2\nline3\nline4\nline5")
        (goto-char buf-point)
        (mapc (lambda (wp) (set-window-point (car wp) (cdr wp))) w-points)))
    (message "Ran update")))

(setq example-timer (run-at-time t 5 #'example))

Now with a configuration of two windows, switch to the example buffer in one of them, and move down a few lines. Switch to the other window, you should see the window point stay the same after every update.

If you then invoke M-x (though any kind of minibuffer interaction will suffice), wait for an update to occur, and then cancel the invocation using C-g, then you should see the point in the window displaying the example buffer go back to the start of the window. Edit: I've created a video here: https://user-images.githubusercontent.com/17688577/210167335-f7a4d50f-dbaf-4ffc-b1e0-38c5612ed2e3.mp4

What can I do to make this second case not happen so that the window point stays the same regardless?

2 Answers 2

1

Trying your example with emacs -Q (no init file), but after changing (get-buffer-window-list buf) to (get-buffer-window-list buf nil t), seems to work for me.

IOW, change optional arg ALL-FRAMES to t. Maybe you were testing without being in the frame where you had the *Example* windows? By default, get-buffer-window-list uses only the windows of the selected frame. Here's what the doc says:

ALL-FRAMES nil or omitted means consider all windows on the selected frame, plus the minibuffer window if specified by the MINIBUF argument. If the minibuffer counts, consider all windows on all frames that share that minibuffer too. The following non-nil values of ALL-FRAMES have special meanings:

  • t means consider all windows on *all existing frames&.

  • visible means consider all windows on all visible frames on the current terminal.

  • 0 (the number zero) means consider all windows on all visible and iconified frames on the current terminal.

  • A frame means consider all windows on that frame only.

Anything else means consider all windows on the selected frame and no others.

1
  • Thanks for taking a look. However, I find I get the same behaviour setting the ALL-FRAMES flag to t (using emacs -Q), and I'm using only one frame. I've also created a video (linked in the question) showing the behaviour I'm seeing, hopefully that gives a better idea of what's going on than I can describe (: Jan 1, 2023 at 10:19
0

I found (setq read-minibuffer-restore-windows nil) gives the desired behaviour. From the documentation of read-minibuffer-restore-windows:

Non-nil means restore window configurations on exit from minibuffer.

Which includes window points, so changes to the window configuration as a result of a timer run whilst the minibuffer is active are reverted. Note as long as you don't remove minibuffer-restore-window from minibuffer-exit-hook the *Completions* window will still be closed:

However, if minibuffer-restore-windows is present
in minibuffer-exit-hook, exiting the minibuffer will remove the window
showing the *Completions* buffer, if any.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.