The more I remove code from my init.el to rely on Emacs defaults, the more I am getting used to it. This means I stopped using the likes of nswbuff and counsel-projectile, but it doesn’t mean there isn’t room for small tweaks.

The basic switch-to-buffer (C-x b) does exactly what it says: it lets you switch to a buffer of your choice. Now, if you play around in Emacs for a while you end up with many open buffers such as *Messages*, *Flymake log*, *Help*, *Ibuffer*, etc. Usually when I want to switch to a buffer I start typing and fido-mode gets me there, but the output of vanilla switch-to-buffer is still a bit cluttered with buffers I never jump to.

(defvar mu-ignored-buffers
'("\\ " "^\\*Async" "^\\*Compile-Log" "^\\*Completions" "^\\*Flymake"
"^\\*Messages" "^\\*eldoc" "^\\*envrc" "\\*tramp" "^\\*xref")
"A list of predicates for buffers to ignore.")

(defun mu-switch-to-buffer (buffer-or-name)
"Switch to BUFFER-OR-NAME but ignore specific buffers."
(interactive
(other-buffer (current-buffer))
(confirm-nonexistent-file-or-buffer)
(lambda (buf)
(not
(seq-contains-p
mu-ignored-buffers (car buf) #'string-match-p))))))
(switch-to-buffer buffer-or-name))


The key point in mu-switch-to-buffer is the fourth argument passed to read-buffer.

Optional arg PREDICATE, if non-nil, is a function limiting the buffers that can be considered. It will be called with each potential candidate, in the form of either a string or a cons cell whose car’ is a string, and should return non-nil to accept the candidate for completion, nil otherwise.

Note that I am using mu-ignored-buffers only in mu-switch-to-buffer. Ibuffer still shows the ignored buffers to me. If I’ll ever get particularly angry at those buffers, I could hide them in Ibuffer as well by adding them to ibuffer-never-show-predicates. These days, though, teenage angst is far behind myself.