Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

emacs: is before-save-hook a local variable?

Tags:

emacs

elisp

how would I figure this out?

I added delete-trailing-whitespace to the before-save-hook in my c-mode-common-hook, but it looks like delete-trailing-whitespace is getting called for every file, not just buffers using c-mode and derivatives.

Can I make the before-save-hook buffer local?

like image 738
Cheeso Avatar asked Dec 19 '09 02:12

Cheeso


4 Answers

Yes create a .dir-locals.el file in your project root directory with this contents:

((c-mode . ((before-save-hook . (lambda() (delete-trailing-whitespace)) )) ))

This will add this hook only to c-mode buffers below this directory.

But if you only want a specific file and not a whole directory you should be able to add this to top of file using File Local Variables:

-*- eval: (setq before-save-hook (lambda() (delete-trailing-whitespace))); -*-

or bottom of file like this:

;;; Local Variables: ***
;;; eval: (setq before-save-hook (lambda() (delete-trailing-whitespace))) ***
;;; End: ***
like image 170
cjohansson Avatar answered Nov 02 '22 04:11

cjohansson


No, the variable before-save-hook is not naturally buffer local. The variable's documentation does not say it's buffer local or say it will automatically become buffer local when set.

If you want to add a buffer-local hook to it, the correct way to do this is just to use the optional LOCAL parameter of the standard add-hook function:

(add-hook 'before-save-hook 'foo nil t)

The add-hook documentation says:

The optional fourth argument, LOCAL, if non-nil, says to modify the hook's buffer-local value rather than its global value. This makes the hook buffer-local, and it makes t a member of the buffer-local value. That acts as a flag to run the hook functions of the global value as well as in the local value.

The selected answer to add it to local-write-file-hooks is wrong, I believe. If you look at the documentation for that function, on emacs 24.3, it says the variable is obsolete since 22.1, and you should use write-file-functions. And if you lookup the documentation of write-file-functions, it describes more complex behavior and says at the end that "To perform various checks or updates before the buffer is saved, use `before-save-hook'".

like image 40
algal Avatar answered Nov 02 '22 05:11

algal


Add it to write-contents-functions instead:

(add-hook 'c-mode-common-hook
  (lambda()
    (add-hook 'write-contents-functions
      (lambda()
        (save-excursion
          (delete-trailing-whitespace)))
      nil t)))

As the Emacs Lisp Reference Manual explains:

This works just like write-file-functions, but it is intended for hooks that pertain to the buffer's contents, not to the particular visited file or its location. Such hooks are usually set up by major modes, as buffer-local bindings for this variable. This variable automatically becomes buffer-local whenever it is set; switching to a new major mode always resets this variable, but calling set-visited-file-name does not.

This works properly for me in Emacs 24.2.1 (i.e., it deletes all trailing whitespace from C files but preserves trailing whitespace in all other file types).

like image 22
Emerick Rogul Avatar answered Nov 02 '22 05:11

Emerick Rogul


Never wanted to do this before, but this should work:

(set (make-local-variable 'before-save-hook) '((lambda() (rg-msg "foobie")))) 

In general C-h v will prompt for a variable name and display a description telling you whether the var is buffer-local.

before-save-hook is a variable defined in `files.el'. Its value is nil

This variable is potentially risky when used as a file local variable.

Documentation: Normal hook that is run before a buffer is saved to its file.

You can customize this variable.

vs.

next-error-function is a variable defined in `simple.el'. Its value is nil

Automatically becomes buffer-local when set in any fashion. This variable is potentially risky when used as a file local variable.

Documentation: Function to use to find the next error in the current buffer. The function is called with 2 parameters:

[...]

like image 34
rgiar Avatar answered Nov 02 '22 05:11

rgiar