I want to customize cc-mode to execute a function before saving. One solution would be to modify cc-mode keymap to bind C-x C-s to a function which performs the work I need and then saves it.

My question is whether there is a hook I could customize for this? The CC Hooks docs don't mention a before-save-hook specifically for cc-mode. How should this be done through a hook?

Alternatively, how do I do this through defadvice? From reading the manual, the only way I could see was to enable the advice before saving and then disable after the work is done. This sounds cumbersome. What would be the idiomatic way of using advices?

  • 3
    The function you add to before-save-hook can check the current major mode (e.g. (eq major-mode ...)) and do nothing if it does not match the mode you are customizing. – Constantine Dec 16 '14 at 21:28
  • @Constantine Agreed. I wanted to check through if there is something more "built-in" for this kind of thing. IIRC haskell-mode has at least one of after/before-save hooks and I assumed this was standard practice for prog-modes. – Pradhan Dec 16 '14 at 21:31
  • @Constantine: could you convert your comment to an answer (expanding a little, of course)? – Dan Dec 17 '14 at 17:02
  • 1
    See this thread for an example use of after-save-hook; you can use the same sort of procedure but substitute before-save-hook. – Dan Dec 19 '14 at 12:45

One fairly common way of restricting the action of a hook to a particular major mode is to check the value of major-mode.

For example, this hook prints a message before saving buffers using c++-mode:

(defun my-c++-mode-before-save-hook ()
  (when (eq major-mode 'c++-mode)
    (message "It's never too early to start saving (C++ code)!")))

(add-hook 'before-save-hook #'my-c++-mode-before-save-hook)

As a side note: sometimes it can be useful to check if a major mode is derived from CC Mode; we can do this by checking if c-buffer-is-cc-mode is not nil:

(defun my-cc-mode-before-save-hook ()
  (when c-buffer-is-cc-mode
    (message "Saving a buffer with a major-mode derived from CC Mode.")))

Alternatively, use a local hook:

(add-hook 'c++-mode-hook
          (lambda () (add-hook 'before-save-hook MY-HOOK-FUNC nil 'local)))

This adds MY-HOOK-FUNC to the buffer-local before-save-hook of each C++ Mode buffer, or any buffer in a mode derived of C++ Mode.

I find this more elegant that explicitly checking major-mode, and it has the advantage that you can disable the before-save-hook locally for each buffer with M-: (remove-hook 'before-save-hook MY-HOOK-FUNC 'local) without affecting any other buffers.


I once needed something like that for autocompiling my elisp files when saved, I used a approach like this (converted the approach to cc-mode):

(add-hook 'c-common-hook #'(lambda ()
                              (add-hook 'before-save-hook #'(lambda ()
                                                               (funcall #'YOUR-FUNC-HOOK)))))
  • 1
    First, did you mean c-mode-common-hook? Second, it looks like it will add the function to before-save-hook the first time you enter a C-related language, but then that function will be called just before every save on every buffer. What OP needs to do is run the function conditional on the buffer being in a specific mode (see @Constantine's comment for how). – Dan Dec 17 '14 at 17:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.