7

I have two frames open with the following window splits:

Frame 1   Frame 2
|---+---+ |------|
|a  |b  | |d     |
|   |   | |      |
|---+---+ |      |
|c      | |      |
|---+---+ |------|

Say that I am in window "a" or "b". Sometimes when I call a function that needs a window, a new, tiny one "e" will be created instead of using a current one. This new window is often too small to be of use.

Frame 1   Frame 2
|---+---+ |------|
|a  |b  | |d     |
|   |   | |      |
|---+---+ |      |
|c  |e  | |      |
|---+---+ |------|

How could I open new windows in one of the currently existing vertical windows, "a", "b", or "d"?

I have experienced this issue with at least occur and xref-find-definitions-other-window.


The crux of the issue seems to be with the display-buffer function. At first glance it seemed like I could use display-buffer-in-side-window to get the behavior I want. In the case of occur, I came up with

(setq
 display-buffer-alist
 `(("\\*Occur\\*"
    display-buffer-in-side-window
    (side . right)
    (slot . 0)
    (window-width . fit-window-to-buffer))))

This has two problems.

First, it turns out that a side window isn't a window like "b" is to "a". Instead, it is a 'hidden' window that can be toggled. For instance, the above code does the following when in window "a", "b", or "c"

Frame 1       Frame 2
|---+---+---| |---|
|a  |b  |e  | |d  |
|   |   |   | |   |
|---+---+   | |   |
|c      |   | |   |
|---+---+---| |---|

and does the following when in "d"

Frame 1   Frame 2
|---+---+ |---|---|
|a  |b  | |d  |e  |
|   |   | |   |   |
|---+---+ |   |   |
|c      | |   |   |
|---+---+ |---|---|

Unfortunately, Frame 2 lives on a vertically aligned monitor and the windows "d" and "e" are too narrow to be convenient. It's the same kind of problem as before!

The second problem is that it relies on an explicit buffer name. When using xref-find-definitions-other-window, the buffer name varies.

Lorem Ipsum
  • 4,327
  • 2
  • 14
  • 35

1 Answers1

3

You can invoke windmove-display-up/-down/-left/-right, windmove-display-same-window (C-M-S-0) or windmove-display-new-tab (C-M-S-t) right before making a new buffer to specify where to put it.

The function windmove-display-default-keybindings sets up key bindings for the directional windmove-display-* commands. Withouth arguments, it sets S-M-<arrow key> as the key bindings, so that, for instance, S-M-right followed by C-x 4 b tells Emacs to display the next buffer in the window at the right (creating it if necessary). windmove-display-default-keybindings can take as argument a list of modifiers that it will use in place of the default ones. For example, (windmove-display-default-keybindings '(control meta shift)) sets the key bindings to C-M-S-<arrow keys>.

So, say you have evaluated (windmove-display-default-keybindings '(control meta shift)), you're in window a and you want to use xref-find-definitions-other-window (plain xref-find-definitions doesn't obey windmove-* functions). You can open the buffer with the definition

  • in the current window with C-M-S-0 M-x xref-find-definitions-other-window RET;
  • in window b with C-M-S-→ M-x xref-find-definitions-other-window RET;
  • in window c with C-M-S-↓ M-x xref-find-definitions-other-window RET;
  • in another tab with C-M-S-t M-x xref-find-definitions-other-window RET;

Same for occur: C-M-S-0 M-s o REGEXP RET, and so on. windmove-* functions also work on clickable text with C-M-S-0 mouse-2 (middle click) etc..

I don't know how to open the buffer in another frame (window d).

Arch Stanton
  • 1,525
  • 9
  • 22
  • At least on Emacs 28, calling `windmove-display-default-keybindings` does not setup the Shift-Meta+, , , keybindings for for the `windmove-display-{up,down,...}` functions. These are super-useful but with paredit, transient and org there are many conflits in the usual bindings. – alephnull Apr 18 '21 at 03:24