display-buffer
ERC supports the “action” interface used by display-buffer and friends from window.el. See Displaying Buffers in Emacs Lisp, for specifics. When ERC displays a new or “reassociated” buffer, it consults its various buffer-display options, such as erc-buffer-display, to decide whether and how the buffer ought to appear in a window. Exactly which one it consults depends on the context in which the buffer is being manifested.
For some buffer-display options, the context is pretty cut and dry. For instance, in the case of erc-receive-query-display, you’re receiving a query from someone you haven’t yet chatted with in the current session. For other options, like erc-interactive-display, the precise context varies. For example, you might be opening a query buffer with the command /QUERY bob RET or joining a new channel with /JOIN #chan RET. Power users wishing to distinguish between such nuanced contexts or just exercise more control over buffer-display behavior generally can elect to override these options by setting one or more to a “display-buffer-like” function that accepts a buffer and an action argument.
Examples
In this first example, a user-provided buffer-display function displays new server buffers in the current window when issuing an M-x erc-tls RET and in a split window for all other interactve contexts covered by the option erc-interactive-display, like clicking an ‘irc://’-style URL (see URL).
(defun my-erc-interactive-display-buffer (buffer action)
"Pop to BUFFER when running \\[erc-tls], clicking a link, etc."
(when-let ((alist (cdr action))
(found (alist-get 'erc-interactive-display alist)))
(if (eq found 'erc-tls)
(pop-to-buffer-same-window buffer action)
(pop-to-buffer buffer action))))
(setopt erc-interactive-display #'my-erc-interactive-display-buffer)Observe that ERC supplies the names of buffer-display options as action alist keys and pairs them with contextual constants, like the symbols ‘erc-tls’ or ‘url’, the full lineup of which are listed below.
In this second example, for Emacs 29 and above, the user writes three predicates that somewhat resemble the “display-buffer-like” function above. These too look for action alist keys sharing the names of ERC’s buffer-display options (and, in one case, a module’s minor mode).
(defun my-erc-disp-entry-p (_ action)
(memq (cdr (or (assq 'erc-buffer-display action)
(assq 'erc-interactive-display action)))
'(erc-tls url)))
(defun my-erc-disp-query-p (_ action)
(or (eq (cdr (assq 'erc-interactive-display action)) '/QUERY)
(and (eq (cdr (assq 'erc-receive-query-display action)) 'PRIVMSG)
(member (erc-default-target) '("bob" "alice")))))
(defun my-erc-disp-chan-p (_ action)
(or (assq 'erc-autojoin-mode action)
(and (eq (cdr (assq 'erc-buffer-display action)) 'JOIN)
(member (erc-default-target) '("#emacs" "#fsf")))))You’ll notice we ignore the buffer parameter of these predicates because ERC ensures that buffer is already current (which is why we can freely call erc-default-target). Note also that we cheat a little by treating the action parameter like an alist when it’s really a cons of one or more functions and an alist.
To complement our predicates, we set all three buffer-display options referenced in their action-alist lookups to display-buffer. This tells ERC to defer to that function in the display contexts covered by these options.
(setopt erc-buffer-display #'display-buffer
erc-interactive-display #'display-buffer
erc-receive-query-display #'display-buffer
;;
erc-auto-reconnect-display 'bury)The last option above just tells ERC to avoid any buffer-display machinery when auto-reconnecting. (For historical reasons, ERC’s buffer-display options use the term “bury” to mean “ignore” rather than bury-buffer.)
Finally, we compose our predicates into buffer-match-p conditions and pair them with various well known display-buffer action functions and action-alist members.
(setopt display-buffer-alist
;; Create new frame with M-x erc-tls RET or (erc-tls ...)
'(((and (major-mode . erc-mode) my-erc-disp-entry-p)
display-buffer-pop-up-frame
(reusable-frames . visible))
;; Show important chans and queries in a split.
((and (major-mode . erc-mode)
(or my-erc-disp-chan-p my-erc-disp-query-p))
display-buffer-pop-up-window)
;; Ignore everything else.
((major-mode . erc-mode)
display-buffer-no-window
(allow-no-window . t))))Of course, we could just as well set our buffer-display options to one or more homespun functions instead of bothering with display-buffer-alist at all (in what would make for a more complicated version of our first example). But perhaps we already have a growing menagerie of similar predicates and like to keep everything in one place in our init.el.
Action alist items
Option-based keys:
All keys are symbols, as are values, unless otherwise noted.
- ‘
JOIN’ - ‘
NOTICE’ - ‘
PRIVMSG’ - ‘
erc’ (entry point called non-interactively) - ‘
erc-tls’
- ‘
- ‘
/QUERY’ - ‘
/JOIN’ - ‘
/RECONNECT’ - ‘
url’ (hyperlink clicked) - ‘
erc’ (entry point called interactively) - ‘
erc-tls’
- ‘
- ‘
NOTICE’ - ‘
PRIVMSG’
- ‘
- something non-
nil
- something non-
Module-based (minor-mode) keys:
erc-autojoin-mode- channel name as a string, e.g.,
"#chan"
- channel name as a string, e.g.,