This Time Self-Hosted
dark mode light mode Search

Per-buffer trailing whitespace killing

As you might know if you read my blog since a long time ago, I’m an Emacs user, or should I say GNU Emacs? Oh well that’s not important right now.

While some of the features, like the emacs-daemon support sometimes drive me crazy because they don’t work properly, there are quite a few that are very very useful; for instance, I can use su to access files as root, both locally and on the server, still using the same editor windows (sorry, frames) as the local files.

From time to time, though, I end up having to do some stuff that Emacs does not, by default, allow me to do. Yesterday, the problem that came up was deleting the trailing whitespace from all the lscube sources when opening the files (and also when saving). There is a function that allows to delete all trailing whitespace, delete-trailing-whitespace with very little fantasy, and it’s easy enough to add it to the find-file-hooks or write-file-hooks lists so that the whitespace is removed after opening or before saving. But unfortunately doing it for all files means applying it to lots of places where I don’t want it to happen.

I’ve searched around but I couldn’t find a way to do this conditionally; some major and minor modes, like the ebuild mode that gives emacs ways to deal with ebuild files, and a quick interface to ebuild commands (unpack, compile, and so on so forth), calls the function during the write phase so that the ebuilds don’t have trailing whitespace (repoman would check for that, so it’s useful to kill them as soon as they are found out). Unfortunately, doing so on a per-project basis seemed to me non-trivial.

First of all the .dir-locals.el file, that allows to provide special buffer-local variables for all the files under a given subtree, does not seem to allow executing special hooks code, it only allows to set variables. This is probably a good idea from a security point of view since this is automatically loaded on each file opening. But adding the function to the general hooks there, also does not work. So I decided simply to write my own hook, that can be configured through a buffer-local variable:

(setq do-delete-trailing-whitespace nil)
(make-variable-buffer-local 'do-delete-trailing-whitespace)

(defun maybe-delete-trailing-whitespace () ""
  (and do-delete-trailing-whitespace
       (progn
     (delete-trailing-whitespace)
     )))

(add-hook 'find-file-hooks 'maybe-delete-trailing-whitespace)
(add-hook 'write-file-hooks 'maybe-delete-trailing-whitespace)

Then I can just set the do-delete-traling-whitespace variable to t in the .dir-locals.el and the trick is served. Lovely.

And this is my first piece of useful elisp code!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.