I want to kill all buffers visiting a file in a given directory, keeping all others. However, my function bombs out when it reaches the #<buffer *Minibuf-1*>
; the minibuffer isn't visiting a file.
(defun my-kill-all-visiting-buffers (dir)
"Kill all buffers visiting DIR."
(interactive)
(mapcar
(lambda (buf)
(and (string-match-p
(regexp-quote dir)
(file-name-directory (buffer-file-name buf)))
(kill-buffer buf)))
(buffer-list)))
In Python-land, I would ask for forgiveness and wrap it in a try-except
. How would I handle this in the land of lisp?
You could handle the exception with something like condition-case
which elisp has. Or you could just do something like this (avoiding the regexp-quotery as well):
(defun my-kill-all-visiting-buffers (dir)
"Kill all buffers visiting DIR or any subdirectory of DIR"
(interactive "Ddirectory: ")
(mapc
(lambda (buf)
(let ((bfn (buffer-file-name buf)))
(when (and (not (null bfn))
(file-in-directory-p bfn dir))
(kill-buffer buf))))
(buffer-list)))
There are probably better approaches.
(not (null x))
is the same as x
but I use it intentionally so when I read it I know I am checking for x
not being a conceptually void value, rather than it just being false.
This avoids regexp operations (originally string=
now string-prefix-p
), because, famously:
Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.
Instead it uses file-in-directory-p
which asks exactly the question it wants the answer to: is file
in a directory or any subdirectory of dir
? (Thanks to Stefan for this, which I didn't know about.)
All of the above is legal in Emacs 26.2: I don't keep track of which things in elisp changed & arrived when any more.
Elisp is not that close to many other dialects of Lisp in use other than rather superficially: techniques which are used in elisp may or may not apply to other languages in the family but often don't.