Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

prevent emacs commands from showing new buffers in other windows

Tags:

emacs

svn

I use emacs in console mode (i.e. no mouse, one frame) with a fixed four window configuration:

+------+------+
| win  | win  |
|  1   |   3  |
+------+------+
| win  | win  |
|  2   |   4  |
+------+------+

Window 3 is my main editing window, I spend most of the time in that one. Windows 1 and 2 hold the same two buffers all the time, I rarely change into these windows because the buffers auto-update themselves and they contain read-only information. Windows 4 is my satellite window, and it's nice that most emacs commands that open a new buffer (e.g. grep, compilation commands, etc) show that new buffer always in Window 4. That makes life very easy because I bound F12 to jump directly between Window 3 and Window 4 and back.

The bad bloke is psvn.el. The svn-status buffer is always opened in Window 3, as desired.
But all other buffers (*svn-diff*, *svn-log*, ...) open randomly in Window 1, 2 or 3, and I can never predict in which one they'll open. Sometimes, the same buffer is even shown on two of those windows at the same time, and that's driving me mad!

How do I tell emacs/psvn to stop doing that? I tried all the usual measures (tweaking same-window-buffer-names, split-height-threshold, split-width-threshold, ...), but nothing's worked so far :-(

Please no solutions involving ecb.

like image 589
Alexander Czutro Avatar asked Feb 13 '14 17:02

Alexander Czutro


2 Answers

Building on what @lawlist said, here is an example of how to override the display-buffer functionality by writing your own display-buffer function and adding an element to display-buffer-alist.

Here we have an interactive function that will mark the currently selected window as the "satellite" window:

(defun mark-this-window-as-satellite ()
  "Mark the current window as the satellite window."
  (interactive)
  (mapc (lambda (win) (set-window-parameter win 'satellite nil))
    (window-list))
  (set-window-parameter nil 'satellite t)
  (message "Window: %s is now the satellite window." (selected-window)))

This is a helper which will allow us to scan and find the satellite window:

(defun get-satellite-window ()
  "Find and return the satellite window or nil if non exists."
  (find-if (lambda (win) (window-parameter win 'satellite)) (window-list)))

We then write a function that will override display-buffer's behavior. This function will look for a satellite window and display the buffer there:

(defun display-buffer-in-satellite (buffer ignore)
  "Display the buffer in the satellite window, or the first window \
    it finds if there is no satellite."
  (let ((satellite-window (or (get-satellite-window)
                              (first (window-list)))))
    (select-window satellite-window)
    (display-buffer-same-window buffer nil)
    (display-buffer-record-window 'reuse satellite-window buffer)
    satellite-window))

Lastly, you nee to add a regexp/function pair to display-buffer-alist that will make all your SVN buffers use the new satellite function:

(push '("\\*svn-" display-buffer-in-satellite) display-buffer-alist)

You can add similar elements for other bothersome modes as well.

like image 130
Jordon Biondo Avatar answered Nov 16 '22 12:11

Jordon Biondo


Maybe you could mark windows 1 and 2 to be dedicated. This will prevent anything to change the buffer they display (you will even need to undedicate them in the - supposedly rare - event that you want to manually switch buffers in them using C-xb).

If you have dedicated-mode installed, just run M-xdedicated-mode in the relevant windows.

If not, you can just define your own small function to mark windows as dedicated:

(defun my-dedicated-window-toggle ()
  "Toggle `window-dedicated-p' in the current window"
  (interactive)
  (set-window-dedicated-p
    (selected-window)
    (not (window-dedicated-p))))
like image 26
François Févotte Avatar answered Nov 16 '22 12:11

François Févotte