5

M-x view-echo-area-messages (bound to C-h e by default) is used to see the *Messages* buffer.

I would like to get the following behavior when I press C-h e:

  1. If the frame has just 1 window, split the frame to create a new window and show *Messages* in that new window.
  2. If the frame already has 2 or more windows, display *Messages* in the other window (not the current one).
  3. If the current window is already displaying *Messages* buffer, do NOT do anything (I tend to press C-h e by mistake even when I am in the *Messages* buffer).

I am able to achieve points 1 and 2 above using the below:

;; Control where the *Messages* buffer opens (add-to-list 'display-buffer-alist '("\\*Messages\\*" . ((display-buffer-reuse-window display-buffer-pop-up-window) . ((inhibit-same-window . t))))) 

But with the above elisp snippet, if I am already in a window with *Messages* and if I do C-h e, it pops up another window displaying the same buffer.

I basically need emacs to ignore (inhibit-same-window . t) if the current buffer matches "\\*Messages\\*". How do I do it?

2 Answers 2

4
(defun foo () (interactive) (unless (equal "*Messages*" (buffer-name (window-buffer))) (display-buffer "*Messages*" (if (one-window-p) 'display-buffer-pop-up-window 'display-buffer-reuse-window)))) (global-set-key (kbd "C-h e") 'foo) 
2
  • Thanks! So it looks like it inhibits opening the buffer in the same window by default when it does display-buffer-reuse-window. Commented May 27, 2015 at 20:49
  • Interesting.. from the source code of display-buffer, if the second arg action is non-nil and NOT a list (in the let form .. (inhibit-same-window (and action (not (listp action))))), inhibit-same-window is set to t. Commented May 27, 2015 at 21:07
4

While @Drew's solution works as I wanted, I was looking for a generic solution that I can apply to multiple cases; not just to *Messages* buffer.

Step 1: General Setup

Advise display-buffer to not execute if the current buffer is same as the to-be-displayed buffer if the new ALIST entry inhibit-duplicate-buffer is non-nil.

(defun modi/execute-display-buffer-if-nil (buffer-or-name &optional action frame) "This functions advices `display-buffer' such that `display-buffer' gets executed only if this function returns `nil'. This function returns `t' when below two conditions are true: 1. BUFFER-OR-NAME has a matching entry in `display-buffer-alist' with a non-nil `inhibit-duplicate-buffer' entry in its ALIST. 2. BUFFER-OR-NAME is same as the current buffer." ;; logic borrowed from the `display-function' definition (if (null display-buffer-function) (let* ((user-action (display-buffer-assq-regexp (buffer-name buffer-or-name) display-buffer-alist action)) ;; end of borrowed logic (inhibit-duplicate-buffer (cdr (assq 'inhibit-duplicate-buffer user-action)))) (and inhibit-duplicate-buffer ; condition 1 (equal buffer-or-name (window-buffer)))) ; condition 2 nil)) (advice-add 'display-buffer :before-until #'modi/execute-display-buffer-if-nil) 

Note that this advice style needs emacs 24.4+.

Step 2: Configuration specific to *Messages* buffer

Use display-buffer-alist to set the buffer displaying rules for *Messages* buffer; now setting a non-nil value for the new ALIST entry inhibit-duplicate-buffer.

;; Control where to display the *Messages* buffer (add-to-list 'display-buffer-alist '("\\*Messages\\*" . ((display-buffer-reuse-window display-buffer-pop-up-window) . ((inhibit-duplicate-buffer . t) (inhibit-same-window . t))))) 
1
  • I realized I don't need the above complicated solution. With the shackle package, I simply need to add ("*Messages*" :select nil :other t) to the shackle-rules alist. Commented Jun 4, 2015 at 14:57

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.