|
|
Vim 的 C-p 和 C-n 命令非常好用,因为它可以自动补全一些内容。在写 C 代码时,vim 会自动打开头文件,补全函数名。例如,在输入下面的代码时:
- #include <stdio.h>
- int main(void)
- {
- int c;
- while ((c = get
复制代码
光标此时位于 get 之后。按下 C-p 并多按几次,vim 就会自动补上 getchar。这个功能很方便。
Emacs 中提供了 hippie-expand 来完成类似的功能。我试了一下,效果并没有 vim 里那样好,因为 Emacs 并不会像 vim 那样自动打开程序中包含的头文件。但是,一旦打开了头文件,Emacs 就可以工作得一样好,甚至更好(在我的试验中,Emacs 会根据上下文只给出特定的备选答案,如函数名,而 vim 则会给出与上下文不相关的备选答案)。所以只要在打开 C/C++ 文件时自动打开它们包含的头文件就可以了。搜索了一下,这个功能似乎不是 Emacs 自带的,我也没有在网上找到,所以自己写了一个,虽然不完善,但凑合着可用了。
把下面的代码加到 ~/.emacs 中:
- (defgroup xgp-c-header-files nil
- "Group for reading C/C++ header files."
- :group 'c)
- (defcustom xgp-c-system-include-paths
- '("/usr/include"
- "/usr/local/include")
- "List of directories where C/C++ header files are found."
- :type '(repeat string)
- :group 'xgp-c-header-files)
- (defun xgp-c-define-local-variables ()
- "Make variable XGP-C-USER-INCLUDE-PATHS directory of file in the current buffer."
- (make-local-variable 'xgp-c-user-include-paths)
- (setq xgp-c-user-include-paths (list (file-name-directory (buffer-file-name)))))
- (defun xgp-c-load-header-files-in-current-buffer ()
- "Try load C/C++ header files included by file in the current buffer.
- First search in the directory relative to the directory of the file
- in the current buffer, then user defined directories, then system
- wide directory."
- (interactive)
- (save-excursion
- (goto-char (point-min))
- (let (b e f af)
- (while (and (setq b (re-search-forward "#include[ \t]+" nil t))
- (setq e (re-search-forward "\n" nil t)))
- (setq f (buffer-substring-no-properties (1+ b) (- e 2)))
- (if (eq (char-before (1- e)) ?>)
- (dotimes (n (length xgp-c-system-include-paths))
- (setq af (concat (nth n xgp-c-system-include-paths) "/" f))
- (if (file-exists-p af)
- (find-file-noselect af t)))
- (dotimes (n (length xgp-c-user-include-paths))
- (setq af (concat (nth n xgp-c-user-include-paths) "/" f))
- (if (file-exists-p af)
- (find-file-noselect af t)))))
- )))
复制代码
然后把这两个函数加到 c-mode-common-hook 中:
- (defun my-c-mode-common-hook ()
- (xgp-c-define-local-variables)
- (xgp-c-load-header-files-in-current-buffer))
- (add-hook 'c-mode-common-hook
- (function (lambda ()
- (my-c-mode-common-hook))))
复制代码
并将 M-/ 绑定为 hippie-expand:
- (global-set-key (kbd "M-/") 'hippie-expand)
复制代码
就可以了。用 Emacs 打开一个 C/C++ 文件,Emacs 就会自动打开它包含的头文件。回到开头的代码,Emacs 也可以自动补全了。需要注意的几点:
1. 如果加入了新的头文件(即写了新的 #include 的行),就要重新执行 xgp-c-load-header-files-in-current-buffer 命令。
2. 头文件分两种类型:用 <> 包围的和用 "" 包围的。第一种要在系统的目录里找,第二种要在当前目录里找。这些目录的值是用变量保存的。第一种的默认值是 /usr/include 和 /usr/local/include。如果要自定义它,可以使用 M-x customize-variable RET xgp-c-system-include-paths RET 来配置。第二种的值是打开的 C/C++ 文件所在的目录。
也许别人已经写过更完善的程序来解决这个问题了,如果有这样的解决方案,请告诉我。 |
|