'emacs only delete-trailing-whitespace while saving in programming mode
following line removes all training white space while saving.
(add-hook 'write-file-hooks 'delete-trailing-whitespace)
but I want to hook this feature only when i'm in programming mode, so i did
(defun nuke_traling ()
(add-hook 'write-file-hooks 'delete-trailing-whitespace)
)
(add-hook 'prog-mode-hook 'nuke_traling)
which doesn't is not stopping which are not in programming mode.
Solution 1:[1]
Making the hook variable buffer-local has been mentioned. Don't do that. Or rather, don't do it using make-local-variable
.
The normal hook mechanisms have buffer-local support built in -- that's the purpose of the LOCAL
argument to add-hook
. When the hook is run, it runs both the global and the buffer-local values.
So taking the example code in the question, you could change it to use:
(add-hook 'write-file-hooks 'delete-trailing-whitespace nil t)
And then delete-trailing-whitespace
would be called whenever write-file-hooks
was run, but only in the buffers in which prog-mode-hook
had run.
However there are better ways to achieve this.
I agree with Drew that you are better to test whether your mode is derived from prog-mode
, and with juanleon that before-save-hook
is a better hook to use. So you might do something like:
(add-hook 'before-save-hook 'my-prog-nuke-trailing-whitespace)
(defun my-prog-nuke-trailing-whitespace ()
(when (derived-mode-p 'prog-mode)
(delete-trailing-whitespace)))
But what I actually recommend is using either ws-trim or ws-butler to take care of this in a smarter way.
Blindly removing all trailing whitespace from a file is a great way to wind up committing loads of unrelated lines to a version-control repository. Both of the libraries mentioned will ensure that your own commits are free of trailing whitespace, without also introducing unwanted modifications elsewhere in the file.
Solution 2:[2]
write-file-hooks
is obsolete since Emacs-22, replaced by write-file-functions
. But this hook is a bit delicate to use (because it can also be used to perform the write), so I recommend you use before-save-hook
instead. And to make it apply only to the current buffer, just pass a non-nil value for the local
argument of add-hook
, as in:
(defun nuke_traling ()
(add-hook 'before-save-hook #'delete-trailing-whitespace nil t))
(add-hook 'prog-mode-hook #'nuke_traling)
Solution 3:[3]
Yes, because as soon as you enter a prog-mode
mode, you add the function to write-file-hooks
, where it remains. And that hook applies to writing any file, regardless of the mode of its buffer.
Instead of putting that simple function on the hook, you can add a function that tests the mode and only does the whitespace deletion when it is a mode where you want to do that.
Or else you would need to make write-file-hooks
buffer-local (which I doubt you would want want to do --- the hook is used more generally).
Solution 4:[4]
Bad way:
(add-to-list 'write-file-functions 'delete-trailing-whitespace)
Better way is using ws-butler:
(straight-use-package 'ws-butler)
(add-hook 'prog-mode-hook #'ws-butler-mode)
ws-butler-mode
remove spaces only on changed lines.
Solution 5:[5]
You would need to make the variable buffer local:
(defun nuke_traling ()
(make-variable-buffer-local 'write-file-hooks)
(add-hook 'write-file-hooks 'delete-trailing-whitespace))
But I would recommend using before-save-hook
instead:
(defun nuke_traling ()
(add-to-list 'before-save-hook 'delete-trailing-whitespace))
write-file-hooks
may be risky if used as a file-local variable, and documentation recomends using before-save-hook
instead for thing like you want to do.
Solution 6:[6]
In emacs 21 or later you can add this hook to a perticular mode like this:
(add-hook 'prog-mode-hook
(lambda () (add-to-list 'write-file-functions 'delete-trailing-whitespace)))
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Nifle |
Solution 2 | Stefan |
Solution 3 | Drew |
Solution 4 | Dunaevsky Maxim |
Solution 5 | juanleon |
Solution 6 | 3r1k |