这篇文章本来是『走近 Emacs』的内容,当时由于考虑到 Emacs 的用户未必写 C/C++ 代码,因此就将它隔离了出来。前端
当你用 Emacs 打开或新建一份扩展名为 .c
的文件时,Emacs 会自动开启内置的 C 模式。这个模式提供了语法高亮、自动缩进等基本功能。同时 Emacs 也容许用户深度定制符合本身使用习惯的代码编辑功能,前提是你须要对 Emacs Lisp 扩展语言有必定了解。linux
若是你不熟悉也不打算学习 Emacs Lisp 语言,那就只能将他人写好的配置代码扔到 $HOME/.emacs
或 $HOME/.emacs.d/init.el
文件中。如今推荐使用后者做为 Emacs 的配置文件。c++
不少年前我从一个我忘记了他的网络 ID 的家伙那里抄来一段 C 代码的配置:程序员
;;;; c mode ;;;; (defvar xgp-cfsi-left-PAREN-old nil "Command used to input \"(\"") (make-variable-buffer-local 'xgp-cfsi-left-PAREN-old) (defun xgp-cfsi-modify-alist (alist term new) (let ((tl (assq term (symbol-value alist)))) (if tl (setcdr tl new) (add-to-list alist (cons term new))))) (defun xgp-cfsi (style) "Deciding whether using CFSI." (interactive "Style: ") (c-set-style style) (setq indent-tabs-mode nil c-hanging-semi&comma-criteria (quote (c-semi&comma-inside-parenlist))) (xgp-cfsi-modify-alist 'c-hanging-braces-alist 'class-open nil) (xgp-cfsi-modify-alist 'c-hanging-braces-alist 'class-close nil) (local-set-key " " 'self-insert-command)) (defun xgp-cfsi-erase-blanks () "Erase all trivial blanks for CFSI." (interactive) (save-excursion (goto-char (point-min)) (while (re-search-forward "[ \t]+$" nil t) (replace-match "" nil nil)))) (defun linux-c-mode() (define-key c-mode-map [return] 'newline-and-indent) (setq imenu-sort-function 'imenu--sort-by-name) (interactive) (imenu-add-menubar-index) (which-function-mode) (c-toggle-auto-state) (c-toggle-hungry-state) (setq indent-tabs-mode nil) (xgp-cfsi "linux")) (add-hook 'c-mode-common-hook 'linux-c-mode)
这样配置以后,C/C++ 代码编辑功能会强大一些。例如,敲击 Backspace 键能够连续删除多行空行;在代码行尾键入 ; 会自动换行;代码缩进长度变为 8 个空白字符……这些配置,我用了不少年,到如今也不知道它具体都作了些什么。正则表达式
C++ 的代码,由于我平时写的不太多,因此没做配置。不过上述的 C 模式配置的这些功能,也适合 C++ 代码的编辑。segmentfault
你如今所用的 Emacs 版本应该是 >= 24,若是不是,想办法升级吧。不然本节内容不太适合你阅读,除非你懂得如何手动安装 Emacs 扩展包。bash
若是用过 Visual C++.net 或者 Eclipse,想必会对它们的代码编辑器提供的代码自动提示功能念念不忘,于是抱怨 Emacs 的 C 模式未提供此功能。事实上是有的,可是要实现 C/C++ 代码的自动提示,这须要 Emacs 懂得如何去解析 C/C++ 代码,似这类繁重又专业的任务让一个文本编辑器来作,不合常理,更况且 Emacs 并不是 C/C++ 程序员的专用编辑器。网络
Emacs 可以作到的事情必需要与文本编辑直接相关,可是它有能力借助其余工具弥补自身不足。像 C/C++ 代码分析这样的任务,交给一个专业的 C/C++ 编译器最好不过了。虽然借助咱们所熟悉的 gcc 是可行的,但它不如另外一款编译前端 clang 好用,由于后者在设计时就考虑到了与代码编辑器的整合。编辑器
咱们所要作的首先是想办法安装 clang。Gentoo Linux 用户只需:ide
$ sudo emerge -avt clang
而后先去干别的事吧,clang 毕竟是 C++ 写的 C/C++ 编译器,是个挺大的项目,编译耗时会挺长,长的我都忘记了到底须要多久,彷佛比编译 libreoffice 或者 firefox 快一些。
Emacs 自己是没法与 clang 沟通的,可是 Emacs Lisp 能够强大到容许 Emacs 用户自行编写扩展包以实现 Emacs 与 clang 的沟通。因而就有人写出了 company 这个扩展包。
在 Emacs 24 以前的时代,要为 Emacs 安装扩展包,须要从网络上下载扩展包,而后复制到 Emacs 所能搜索到的目录,最后在 Emacs 配置文件中对扩展包进行配置。
从 Emacs 24 开始,Emacs 对扩展包进行统一管理,极大程度上简化了扩展包的搜索与安装过程。打开 Emacs,而后执行 M-x list-packages
,若是网速足够快,应该很快就能看到 Emacs 官方提供的扩展包列表。
待软件包列表出现后,执行 C-s M-r ^ +company
,回车便可让光标跳到 company 扩展包信息所在的文本行,继而敲击 i
键(表示要安装该扩展包),再敲击 x
键(表示执行安装过程),稍等片刻,Emacs 会自动从下载 company 扩展包并安装至 $HOME/.emacs.d
目录。
提示:
C-s
是开启 Emacs 查找模式,M-r
是将查找模式切换为正则表达式查找模式,而^ +companyy
是用于匹配『位于行首且由多个空格与company
字符串构成的字符串』的正则表达式。
若是之后要删除 company 扩展,步骤与安装步骤相似,只是将 i
键替换为 d
键(表示删除)。
company 安装完毕后,在 Emacs 配置文件中作如下配置:
;; 代码补全 (add-hook 'c-mode-hook 'company-mode) (add-hook 'c++-mode-hook 'company-mode)
这样即可将 company 挂接到 Emacs C 模式上。这样,每当 Emacs 打开 C/C++ 文件时company 模式便会被自动开启。
下图是 company 与clang 成功『沟通』后的结果:
因为 clang 默认会去 Linux 标准目录 /usr/include
中去搜索库的头文件,可是有些库的头文件是安装在非标准位置的。例如 PCL 库的头文件,默认安装在 usr/include/pcl-1.7
,若要对 PCL 库函数进行自动补全,那么就须要将这个路径告诉 clang。eigen 库也存在这个问题。解决方法是在项目源码的顶层目录下建立 .dir-locals.el
文件,内容相似于:
((nil . ((company-clang-arguments . ("-I/usr/include/pcl-1.7/" "-I/usr/include/eigen3/")))))
若是谁有更好的让 clang 自动搜索库的头文件路径的方法,还请不吝赐教。