Search code examples
lispelisp

elisp: Handling wrong-type-argument exception


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?


Solution

  • 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.


    Notes

    (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.