Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In emacs, how do I save without running save hooks?

Tags:

emacs

elisp

I have various things set up in my 'before-save-hook. For example, I run 'delete-trailing-whitespace. This is what I want in almost all occasions.

But sometimes, I'm working on files that are shared with other people, and the file already has a bunch of trailing whitespace. If I save the file, I'll get a big diff that's pretty confusing, as my change is buried in dozens or hundreds of meaningless changes. Yes, everyone could just tell their diff tool to not show whitespace changes, but that's something that everyone has to do every time they look at the diff. I'd rather not even have the whitespace change.

Is there anything I can do to save the file without the whitespace changes, short of starting a new instance of Emacs with no init.el file, or with a modified init.el that doesn't have the hook?

like image 773
zck Avatar asked Feb 16 '13 18:02

zck


3 Answers

Here is how I save without triggering delete-trailing-whitespace: C-x C-q C-x C-s C-x C-q: read-only, save, revert read-only

like image 103
Nicolas Douma Avatar answered Oct 26 '22 22:10

Nicolas Douma


A simpler solution I came up with is that my fundamental-mode has no hooks installed, because I want it to be as plain as possible. Thus if I want to save a file without running hooks, I temporarily switch to fundamental-mode.

like image 30
rafalcieslak Avatar answered Oct 27 '22 00:10

rafalcieslak


Based on a comment discussion with @Stefan, here are two possible (untested) solutions:

Use let:

(defun save-buffer-without-dtw ()
  (interactive)
  (let ((b (current-buffer)))   ; memorize the buffer
    (with-temp-buffer ; new temp buffer to bind the global value of before-save-hook
      (let ((before-save-hook (remove 'delete-trailing-whitespace before-save-hook))) 
        (with-current-buffer b  ; go back to the current buffer, before-save-hook is now buffer-local
          (let ((before-save-hook (remove 'delete-trailing-whitespace before-save-hook)))
            (save-buffer)))))))

Use unwind-protect:

(defun save-buffer-without-dtw ()
  (interactive)
  (let ((restore-global
         (memq 'delete-trailing-whitespace (default-value before-save-hook)))
        (restore-local
         (and (local-variable-p 'before-save-hook)
              (memq 'delete-trailing-whitespace before-save-hook))))
    (unwind-protect
         (progn
           (when restore-global
             (remove-hook 'before-save-hook 'delete-trailing-whitespace))
           (when restore-local
             (remove-hook 'before-save-hook 'delete-trailing-whitespace t))
           (save-buffer))
      (when restore-global
        (add-hook 'before-save-hook 'delete-trailing-whitespace))
      (when restore-local
        (add-hook 'before-save-hook 'delete-trailing-whitespace nil t)))))

The problem with the second solution is that the order of functions in the before-save-hook may change.

like image 38
sds Avatar answered Oct 27 '22 00:10

sds