如何告诉Emacs以C++模式打开.h文件?

69

我应该在我的 _emacs(Windows上)文件中添加哪些行来使其在C++模式下打开.h文件?默认是C模式。

6个回答

72

试试这个:

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

无论何时打开.h文件,都将使用C++模式。

这个错误提示是“符号的值作为变量是空的:.h\”,意思是该程序无法识别或找不到名为“.h”的变量。 - vk-code

38

另一种同时使用c-mode和c++-mode的方法是,使用目录本地变量来设置模式。

目录变量在模式设置后进行评估1,所以你可以为C ++项目编写一个.dir-locals.el文件,其中包含这个:

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

当Emacs初始设置为c-mode时,它将改变模式为c++-mode

如果你同时使用C和C++项目,这对于每个项目来说都是一个非常简单的解决方案。

当然,如果你大部分的项目都是C++,你可以将设置为默认值2,然后可以反过来使用这种方法,在适当的情况下切换到。


1normal-mode按照顺序调用(set-auto-mode)(hack-local-variables)函数。有关详情,请参见:如何在我的主模式挂钩中访问目录本地变量?

2要这样做,请添加

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

将以下代码添加到您的.emacs文件中,以默认以C++模式打开.h文件。


3
这是最有用的答案。另外,请注意mode是文件局部变量列表中的特殊形式,仅在此处记录这里 - scry
我已经添加了脚注(2),这样你的答案就是自给自足的,不依赖于其他人。现在,它应该成为被接受的答案。谢谢。 - YSC
这个解决方案会导致.cglsl文件也使用c++-mode。有没有办法强制使用glsl-mode呢? - jco
("\\.glsl\\'" . glsl-mode) 添加到列表 auto-mode-alist 中。 - phils
这个解决方案很棒!然而,以这种方式加载的头文件不会应用通过(c++-mode .设置的目录本地值(至少在Emacs 25中),所以你需要通过(nil .来应用这些值。 - mzuther

24

如果您不想将此应用于每个.h文件,则可以将以下内容添加到C++头文件的底部。

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

对于任何你想在每个文件上设置的 Emacs 变量,这将起作用。Emacs 忽略前导字符,因此请使用适合文件类型的任何注释字符。


谢谢,我没想到你可以用emacs做到这个。 - kujawk
不知道那在每个文件中都起作用。这可能非常有用。谢谢 :) - Plankalkül

22

显然,你也可以将这个放在文件的顶部:

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

// -*-c++-*-

告诉Emacs这是一个C++文件。

我经常在没有对Emacs进行任何配置的情况下使用它,因此我使用这个方法。


4
或者也可以写成:// -*- mode: c++ -*-。您还可以在其中添加其他变量,例如 -*- coding: utf-8; mode: python; tab-width: 4; -*- - donkopotamus

19

由于我经常使用C和C ++,因此我编写了此函数以尝试“猜测”一个.h文件是用于C还是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))

如果这不起作用,我会设置一个键来在C和C++模式之间切换。

;; 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))))

并非完美,也许有更好的启发式方法来判断一个标题是C还是C ++,但对我而言它起作用。


更好的解决方案可能是在文件中编码模式(请参见我的答案),然后定义添加适当行到文件的键。唯一的缺点是不使用emacs的人也会看到它,但由于它在文件底部,所以不应该是什么大问题。 - KeithB
1
这对于你自己的项目来说没问题,但我的解决方案主要是用来处理其他人的项目。你可以将本地变量附加到第三方项目的头文件末尾,但在我看来这需要太多的努力。 - Borbus
我真的很喜欢这个解决方案,它使得定制行为变得非常容易,而无需修改任何源文件。例如,在我的版本中,我使用像(string-match "llvm" (buffer-file-name))这样的东西来确定.h文件是否是c++文件(llvm是一个c++项目)。 - zdav
我可能晚了7年,但我认为更好的确定.h文件是否属于C++的方法是扫描缓冲区中的关键词,如class、namespace、public、private等。此外,为了避免将C头文件标记为C++,只因为它们恰好有一个名为class的变量等,您可以检查这些单词是否在行的开头(当然要考虑缩进)。 - The Gramm

3

我敢肯定我已经看到这个问题得到了适当的回答了?奇怪。

您想要这个:

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

你做了...作者已经删除了它。 - Paul Nathan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接