c++-mode-hook and c-mode-hook appears to run twice

3.9k views Asked by At

I use this command to start emacs

$ emacs -Q c-mode-test.el

then I use C-xC-e to eval every line

(require 'cc-mode)

(add-hook 'c-mode-common-hook '(lambda () (print "hello")))

(add-hook 'c-mode-hook '(lambda () (print "hello c")))

(c-mode)

after this, the minibuffer shows

"hello"

"hello c"

"hello c"
nil

and c++-mode-hook run just the same

(add-hook 'c++-mode-hook '(lambda () (print "hello c++")))

(c++-mode)

the minibuffer

"hello"

"hello c++"

"hello c++"
nil

why it run twice or something wrong.

3

There are 3 answers

0
Craig Citro On

It seems that the language-specific hooks are getting run more than once. You can confirm that this is the case by running (run-hooks c-mode-hook) or (run-hooks c-mode-common-hook), and you'll notice that your print statement only happens once.

The general advice with hooks is to not be dependent on the order in which they're run -- not depending on how many times they're run seems like a natural extension there.

0
UndeadKernel On

You are using the wrong hook for your "C" files. The correct hook to use is "c-mode-hook".

The hook "c-mode-common-hook" is run before every c-style language. That is, the hook is run for many languages such as java, objective-c, awk and others. You can find more information about these hooks here.

0
andygavin On

There is a bug report about this http://debbugs.gnu.org/cgi/bugreport.cgi?bug=16759 I don't think that language hooks are guaranteed to be executed once for a number of language modes. I suspect the issue is due to using define-derived-mode which is a lisp macro for defining a mode that already includes calls to hooks, this means the hooks called in the mode will be an additional execution.

You might want to try the initialization hook. The manual says:

Variable: c-initialization-hook

Hook run only once per Emacs session, when CC Mode is initialized. This is a good place to change key bindings (or add new ones) in any of the CC Mode key maps. See Sample Init File.

The sample it gives is here: https://www.gnu.org/software/emacs/manual/html_node/ccmode/Sample-Init-File.html#Sample-Init-File