3

Often I have multiples windows carefully arranged within a frame.

However, certain command, say M-x man RET will grab one of the visible windows to display its own content. Sometimes this is annoying because the window that was taken away is one that I need to keep it visible.

e.g. I have 3 windows on screen, one useful source-code window and two useless windows. I want to keep the soure-code window visible while checking the man page. But very often Emacs just take away the code-window for the newly opened man page.

One way I can think of is to display the (chronological) open order of each window, so that I can focus point on n-th window and be confident that Emacs will grab (n+1)-th window for new content.

Is there a way to display such order, e.g. in the mode-line of each window?

Or is there another way for better control for displaying new window?

modeller
  • 3,770
  • 3
  • 25
  • 49
  • 3
    Functions that utilize `display-buffer` and related family within `window.el` generally respect a dedicated window: http://www.gnu.org/software/emacs/manual/html_node/elisp/Dedicated-Windows.html – lawlist Aug 23 '14 at 21:50
  • 1
    Although the following link in the manual is more geared towards writing your own code for using the `display-buffer` family of functions, it may be helpful to demonstrate what would be needed to control which window displays a particular buffer: http://www.gnu.org/software/emacs/manual/html_node/elisp/Display-Action-Functions.html For controlling specific buffers, here is a link to an example using the `display-buffer-alist`: http://stackoverflow.com/a/16661081/2112489 – lawlist Aug 23 '14 at 21:58
  • 1
    +1 to @lawlist for mentioning dedicated windows. (Just using separate frames for different buffers is another solution, e.g. non-nil `pop-up-frames` etc.) But trying to control this kind of thing using `display-buffer-alist` is, well, a swamp... (And it seems to change every year, as they try to fix more cases that break or never worked.) On the other hand, perhaps @modeller will be the one to master `display-buffer-alist` and tame buffer/window associations once and for all (and receive a Nobel Prize for the effort and accomplishment). – Drew Aug 23 '14 at 22:04
  • @lawlist, thanks for the link, I will read it , seems long – modeller Aug 23 '14 at 22:28
  • @Drew, thanks for the tips. other frame may be an alternative solution. – modeller Aug 23 '14 at 22:28
  • 3
    A binding to toggle the 'dedicated' state of a window is definitely a super-useful thing to add. Combine that with using `winner-mode` so that you can trivially restore the window configuration to what it was before, and you have something of a workaround for the issue in general. – phils Aug 23 '14 at 23:27
  • 1
    @phils, thanks for the tip. I do have a winner-mode installed. indeed handy. Just not heard of dedicated state before until advised by lawlist and Drew – modeller Aug 24 '14 at 00:43
  • +1 for @phils's suggestion for a toggle for dedicatedness. Never thought of that! (But I'm not really bothered by such problems, since I typically use one window per frame. I do use dedicated windows for buffers with names wrapped in `*`: `*...*`, however.) – Drew Aug 24 '14 at 02:24

2 Answers2

2

A little late to the party but as discussed in the comments, using dedicated windows is a good way to control where new content is displayed (+1 to @lawlist for bringing it up and to @phils for mentioning toggling!).

I'm pretty sure you'd be able to implement a command that toggles dedicatedness yourself at this point, but since I have the code for this handy I'll share it anyway:

(defun toggle-window-dedicated ()
  "Control whether or not Emacs is allowed to display another
buffer in current window."
  (interactive)
  (message
   (if (let (window (get-buffer-window (current-buffer)))
         ; set-window-dedicated-p returns FLAG that was passed as
         ; second argument, thus can be used as COND for if:
         (set-window-dedicated-p window (not (window-dedicated-p window))))
       "%s: Can't touch this!"
     "%s is up for grabs.")
   (current-buffer)))

(global-set-key (kbd "C-c d") 'toggle-window-dedicated)

Now, in a multi-window setup you can simply press C-c d in each window you would like to "protect".

itsjeyd
  • 5,070
  • 2
  • 30
  • 49
  • 1
    I use `` as a binding for this. For my keyboard layout that's the "Pause/Break" key above "Page Up". It's far enough out of the way that I've never used it for anything else, and it seemed like a good mnemonic for the functionality :) – phils Aug 24 '14 at 12:03
  • Thanks for sharing this. This is not working in my case. The "protected" window is populated with something else when opening a buffer from another window. – Emmanuel Goldstein Apr 14 '22 at 13:34
2

I'll throw this example usage of display-buffer-alist into the mix, given that it was mentioned in the comments, and is indeed a general mechanism for controlling how and where buffers are displayed (even though, as Drew indicates, it is far from trivial).

Start with the help for the variable itself:
C-hv display-buffer-alist RET

From there you'll get to the help for display-buffer, and no doubt acquire some idea of the complexities involved :)

In any case, the following is an example of using a custom function to decide how to display buffers named *Buffer List*.

You can easily see that if you can write a function which can figure out how to display a buffer where you want it to, then you can use display-buffer-alist to make it happen.

(defun my-display-buffer-pop-up-same-width-window (buffer alist)
  "A `display-buffer' ACTION forcing a vertical window split.
    See `split-window-sensibly' and `display-buffer-pop-up-window'."
  (let ((split-width-threshold nil)
        (split-height-threshold 0))
    (display-buffer-pop-up-window buffer alist)))

(add-to-list 'display-buffer-alist
             '("\\*Buffer List\\*" my-display-buffer-pop-up-same-width-window))

A key quote regarding the ACTION functions is:

Each such FUNCTION should accept two arguments: the buffer to display and an alist. Based on those arguments, it should display the buffer and return the window.

phils
  • 71,335
  • 11
  • 153
  • 198