0

I am seeing confusing behavior when using switch-to-buffer-other-window.

When there is only a single window, and I run these two commands:

M-x split-window-right

M-x other-window

M-x eval-expression "(switch-to-buffer-other-window (get-buffer "scratch.org"))"

Then there are only two windows open.

However, when there was only a single window, and I run these two commands:

M-x split-window-below

M-x other-window

M-x eval-expression "(switch-to-buffer-other-window (get-buffer "scratch.org"))"

Then emacs opens a third window and switches to the buffer in it.

Instead, I want emacs to switch to the buffer in the existing window above the one I am currently in. How to I achieve this?

1 Answer 1

1

display-buffer is the basic routine that decides how to display a buffer. It uses a variable display-buffer-alist to help it decide. You can modify that variable to use a different action than the default in order to do what you want. C-h f display-buffer gives you a list of action functions, e.g. here is the description of one of them: ‘display-buffer-use-least-recent-window’ -- Try to avoid re-using windows that have recently been switched to. This looks promising, so we define a function that uses that as follows:

(defun my/switch-to-buffer-other-window (buf)
  (let ((display-buffer-alist '((".*" display-buffer-use-least-recent-window))))
    (switch-to-buffer-other-window buf)))

You can then use this function to switch to the buffer in the least-recently-used window:

(my/switch-to-buffer-other-window (get-buffer "*scratch*"))

For (much more) information about display-buffer, consult Displaying buffers in the Emacs Lisp Reference manual.


Keeping the functions separate allows you to use one or the other as the need arises. OTOH, if you want to permanently change the behavior, you could advise the original switch-to-buffer-other-window function to do the new thing:

(defun use-least-recent-window (orig-fun &rest args)
  (let ((display-buffer-alist '((".*" display-buffer-use-least-recent-window))))
    (apply orig-fun args)))

(advice-add 'switch-to-buffer-other-window :around #'use-least-recent-window)

If at any point you want to get rid of the advice, then evaluate the following:

(advice-remove 'switch-to-buffer-other-window  #'use-least-recent-window)

Manipulating the heuristics used for window choice by display-buffer like this can be finicky. I believe there are higher-level libraries to do things like this conveniently, but I haven't used any of them and I cannot even remember names ATM, so I hope others will provide answers that use them. I am under the impression that they trade off flexibility for convenience, but you shouldn't put much stock in that.

EDIT: Here's one such library: emacs-purpose - but as I mentioned, I've never used it and I don't know much about it.

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.