71

What lines should I add to my _emacs (on Windows) file to have it open .h files in C++ mode? The default is C mode.

6 Answers 6

73

Try this:

(add-to-list 'auto-mode-alist '("\\.h\\'" . c++-mode))

Whenever you open .h files, C++-mode will be used.

1
  • this gives me error "Symbol's value as variable is void: \.h\"
    – vk-code
    Commented Apr 28, 2019 at 14:53
38

Another approach for using both c-mode and c++-mode as appropriate, is to use directory local variables to set the mode.

Directory variables are evaluated after the mode has been set1, so you can actually write a .dir-locals.el file for your C++ project containing this:

((c-mode . ((mode . c++))))

And Emacs will change the mode to c++-mode whenever it had initially set it to c-mode.

If you work with a mix of C and C++ projects, this makes for a pretty trivial solution on a per-project basis.

Of course, if the majority of your projects are C++, you might set c++-mode as the default2, and you could then use this approach in reverse to switch to c-mode where appropriate.


1 normal-mode calls (set-auto-mode) and (hack-local-variables) in that order. See also: How can I access directory-local variables in my major mode hooks?

2 To do so, add

(add-to-list 'auto-mode-alist '("\\.h\\'" . c++-mode))

to your .emacs file which open .h files in C++ mode by default.

5
  • 3
    This is the most useful answer. Also, be aware mode is a special form in file-local variable lists and is only documented here.
    – scry
    Commented Mar 17, 2015 at 2:48
  • I've added the footnote (2) so your answer is self-sufficient and doesn't depend on others. Now, it should be the accepted answer. Thx.
    – YSC
    Commented Apr 4, 2017 at 8:50
  • This solution causes c++-mode to be used also for .glsl files. Is there any way to force glsl-mode to be used, instead?
    – jco
    Commented May 8, 2017 at 8:30
  • (add-to-list 'auto-mode-alist '("\\.glsl\\'" . glsl-mode)) ?
    – phils
    Commented May 8, 2017 at 10:44
  • This solution is great! However, header files that are loaded this way do not apply directory local values set via (c++-mode . (at least in Emacs 25), so you will have to apply these values via (nil .. Commented Apr 28, 2020 at 16:55
25

If you don't want this to apply to every .h file, you can add the following to the bottom of your C++ header files.

// Local Variables:
// mode: c++
// End:

This will work for any Emacs variables that you want to set on a per file basis. Emacs ignores the leading characters, so use whatever comment characters are appropriate for the file type.

2
  • Thanks, didn't realize you could do this with emacs.
    – kujawk
    Commented Aug 4, 2010 at 17:05
  • Did not know that worked in ever file. This could be very useful. Thanks :) Commented Aug 25, 2015 at 8:11
24

Apparently you can also put this at the top of the file:

// -*-c++-*-

to tell Emacs it's a C++ file.

I use this since I quite frequently end up on a vanilla Emacs and it works without configuring Emacs in any way.

1
  • 4
    Or also as: // -*- mode: c++ -*-. You can also add other variables in there such as -*- coding: utf-8; mode: python; tab-width: 4; -*- Commented Mar 8, 2016 at 23:29
19

Since I use both C and C++ regularly, I wrote this function to try and "guess" whether a .h file is meant to be C or C++

;; function decides whether .h file is C or C++ header, sets C++ by
;; default because there's more chance of there being a .h without a
;; .cc than a .h without a .c (ie. for C++ template files)
(defun c-c++-header ()
  "sets either c-mode or c++-mode, whichever is appropriate for
header"
  (interactive)
  (let ((c-file (concat (substring (buffer-file-name) 0 -1) "c")))
    (if (file-exists-p c-file)
        (c-mode)
      (c++-mode))))
(add-to-list 'auto-mode-alist '("\\.h\\'" . c-c++-header))

And if that doesn't work I set a key to toggle between C and C++ modes

;; and if that doesn't work, a function to toggle between c-mode and
;; c++-mode
(defun c-c++-toggle ()
  "toggles between c-mode and c++-mode"
  (interactive)
  (cond ((string= major-mode "c-mode")
         (c++-mode))
        ((string= major-mode "c++-mode")
         (c-mode))))

It's not perfect, there might be a better heuristic for deciding whether a header is C or C++ but it works for me.

4
  • A better solution might be to encode the mode in the file (see my answer), and then define keys for adding the appropriate lines to the file. The only drawback is that people who don't use emacs will see this as well, but since its at the bottom of the file it shouldn't be much of an issue.
    – KeithB
    Commented Jul 30, 2010 at 18:42
  • 1
    That's fine for your own projects but my solution is mainly for dealing with other people's projects. You could cat your local variables on to the end of the headers in a 3rd party project but this is way too much effort IMO.
    – Borbus
    Commented Aug 3, 2010 at 18:47
  • I actually like this solution a lot, it makes it easy to customize behaviour without modifying any source files. For instance, in my version I use things like (string-match "llvm" (buffer-file-name)) to determine if a .h file is c++ or not (llvm is a c++ project).
    – zdav
    Commented Oct 2, 2014 at 13:21
  • I am like 7 years late, but I think a better approach to determine if the .h is in c++ is to scan the buffer for words like class, namespace, public, private etc.. Also to avoid labeling C headers as c++ just cause they happen to have a variable named class etc, you can check if those words are at the very start of the line (after indentation ofc).
    – The Gramm
    Commented May 9, 2017 at 10:50
3

I could swear I saw this question answered appropriately already? Weird.

You want this:

(add-to-list 'auto-mode-alist '("\\.h\\'" . c++-mode))
1
  • You did... the author deleted it. Commented Jul 26, 2010 at 20:17

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