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. 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. 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. Jun 4, 2015 at 14:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.