I have a main window displaying buffer
A, and bottom window displaying some project-wide search
┌───────────┐ │ A │ │ │ ├───────────┤ │ results │ └───────────┘
Hitting enter on one of the search results runs compile-goto-error, which ends up calling pop-to-buffer, splitting my main window, and displaying the result on the right:
┌─────┬─────┐ │ A │ R1 │ │ │ │ ├─────┴─────┤ │ results │ └───────────┘
Swithing back to the
results window, hitting enter an another result displays it on the left:
┌─────┬─────┐ │ R2 │ R1 │ │ │ │ ├─────┴─────┤ │ results │ └───────────┘
This annoys me to no end, as I wanted to keep
A visible and continue browsing the results on the right. I don't have a strong left/right preference, I just want pop-to-buffer to be consistent in its choice of window. It's currently choosing the least recently used window, and while I can see the reasoning behind that, it forces me into a game of whacka-mole, bouncing between windows, switching between buffers, etc.
The same problem arises when I hit enter on push-button links in a help buffer.
I'm coming from Vim, where the righthand window is consistently used in such scenarios. I'd like to configure Emacs to make this workflow less disorienting. I have something like this in mind:
- if the relevant buffer is already visible in an existing window, use that window
- if a result was previously displayed, use the same window again if the window is still live
- if the main window has not been split (i.e. there's only one window other than the
resultswindow), use split-window-sensibly and display buffer in the right/lower split
- if the main window has already been split, default to the right/lower split
I'm also open to suggestions for other approaches entirely. I realize that by trying to reproduce a workflow I use in Vim, I might be missing out on a better approach that's achievable in Emacs.
I've written a sort of hacky workaround, though seems to work so far.
(defvar pop-target-window) (make-variable-buffer-local 'pop-target-window) (advice-add 'compilation-goto-locus :around #'ivan-around-compilation-goto-locus) (defun ivan-around-compilation-goto-locus (orig-func &rest args) (advice-add 'pop-to-buffer :override #'ivan-pop-to-buffer) (apply orig-func args)) (defun ivan-pop-to-buffer (buffer &optional action norecord) (advice-remove 'pop-to-buffer #'ivan-pop-to-buffer) (let ((from-buffer (current-buffer)) (reused-window (display-buffer-reuse-window buffer nil))) (cond (reused-window (select-window reused-window norecord)) ((and (bound-and-true-p pop-target-window) (window-live-p pop-target-window)) (window--display-buffer buffer pop-target-window 'reuse) (select-window pop-target-window norecord)) (t (pop-to-buffer buffer action norecord) (with-current-buffer from-buffer (setq-local pop-target-window (selected-window)))))))