1

I have this line in my GNU Emacs configuration which cleans up white spaces when I save:

(add-hook 'before-save-hook 'whitespace-cleanup)

How can I keep this from running in certain modes (Makefile mode, for example)?

Elektito
  • 3,863
  • 8
  • 42
  • 72
  • Out of interest, why are you trying to stop `whitespace-cleanup` from running in those modes, instead of making it work in those modes? – phils Oct 02 '14 at 07:13
  • If you know a way of doing that I'd be very grateful to know. All I know at the moment is that whitespace-cleanup messes up my Makefiles by removing all the TABs. – Elektito Oct 02 '14 at 07:24
  • *Removing* tabs, or *replacing* them (with spaces)? I can't replicate the problem in any case, but *removing* would seem extremely weird. What are the values of the `indent-tabs-mode`, `tab-width`, and `whitespace-style` variables in one of your Makefile buffers? (Use `C-h v` from that buffer). – phils Oct 02 '14 at 07:49
  • 1
    Also, take a look at [ws-trim](ftp://ftp.lysator.liu.se/pub/emacs/ws-trim.el) and [ws-butler](https://github.com/lewang/ws-butler) if you would prefer to only modify whitespace on the lines you actually edit. – phils Oct 02 '14 at 07:57
  • @phils It replaces tabs with spaces. My mistake. Also, `indent-tabs-mode=nil`, `tab-width=8`, `whitespace-style=(face tabs spaces trailing lines space-before-tab newline indentation empty space-after-tab space-mark tab-mark newline-mark)`. I've set `indent-tabs-mode` to `nil` intentionally because I'm not a huge fan of tabs in my source code. Does this cause whitespace-cleanup to replace tabs with spaces. – Elektito Oct 02 '14 at 09:39
  • 1
    Yes, and you've done something very strange for this to be the case, because `makefile-mode` does an explicit `(setq indent-tabs-mode t)` for obvious reasons. Something in your config is overriding that. Find it and fix it. (n.b. `indent-tabs-mode` is automatically buffer-local, so it's nothing to do with your default value for it). – phils Oct 02 '14 at 10:06
  • n.b. At a guess, you may be setting it in a `prog-mode-hook` function. If so, you might wish to modify that function in a similar manner to the answer you've accepted here, in order to omit that setting for `makefile-mode` and derivatives. Alternatively, if you have no need for tabs in non-programming modes, you could simply use `(setq-default indent-tabs-mode nil)` in your init file, and *not* set it in a hook at all. Then you don't need to worry about making exceptions. – phils Oct 02 '14 at 11:27

1 Answers1

3

The following definition will run whitespace-cleanup in modes except the ones given in the condition:

(defun elektito/whitespace-cleanup ()
  (when (not (derived-mode-p 'makefile-mode))
    (whitespace-cleanup)))

(add-hook 'before-save-hook 'elektito/whitespace-cleanup)

This uses derived-mode-p to check the current mode instead of direct comparison, as you mention makefiles, and makefiles use a large number of slightly different modes, all of which are derived from makefile-mode. derived-mode-p accepts multiple arguments to check for different parent modes.

(NB: It is possible to use (unless COND EXPR) instead of (when (not COND) EXPR), but I find that less readable; you might have different preferences.)

Jorgen Schäfer
  • 1,196
  • 6
  • 8
  • 4
    I would go for simply `(derived-mode-p 'makefile-mode 'some-major-mode 'another-major-mode)`, that way it would work even for modes that inherit from `some-major-mode`. – Lindydancer Oct 02 '14 at 07:52
  • 2
    Indeed, thank you, Lindydancer. I did not realize `derived-mode-p` does check for mode equality, too (of course it does, doh!), and did not know it accepts multiple modes. Adjusted the answer accordingly. – Jorgen Schäfer Oct 02 '14 at 08:00