CEDET是emacs非常强大的一个扩展,已经被包含在gnu emacs中,代码补全是个很方便的功能,已经有很多文章介绍过这方面的了,其中算最全面的是
这三篇文章已经详细介绍了如何使用CEDET,其他还有很多文章,但大多是抄这三篇的内容,但是可能还是有很多朋友自动补全上有点小问题。
这里没有使用23.2以后内置的CEDET,而是另外下载的。我所使用的环境为slackware 13.37 x64, emacs 23.3
首先按照上面的三篇文章配置好CEDET,按照CEDET官网上的介绍。
.emacs中添加:
(load-file "~/.cldev/pkgs/cedet-1.0/common/cedet.el")
(global-ede-mode 1)
(semantic-load-enable-code-helpers)
(global-srecode-minor-mode 1)
这几行就算是配置好了基本的CEDET。
1、系统目录头文件、标准库、同文件、同目录下头文件补全
代码补全还需要配置semantic,添加如下配置:
;;; semantic setup
;; (semantic-load-enable-minimum-features)
;; (semantic-load-enable-code-helpers)
;; (semantic-load-enable-gaudy-code-helpers)
(semantic-load-enable-excessive-code-helpers)
(semantic-load-enable-semantic-debugging-helpers)
;;; gcc setup
(require 'semantic-gcc)
;;; smart complitions setup
(require 'semantic-ia)
;;; 快捷键
(defun my-cedet-hook()
(local-set-key [(control return)] 'semantic-ia-complete-symbol)
(local-set-key "\C-c?" 'semantic-ia-complete-symbol-menu)
(local-set-key (kbd "M-n") 'semantic-ia-complete-symbol-menu)
(local-set-key "\C-c>" 'semantic-complete-analyze-inline)
(local-set-key (kbd "M-/") 'semantic-complete-analyze-inline)
(local-set-key "\C-cp" 'semantic-analyze-proto-impl-toggle)
(local-set-key "\C-cd" 'semantic-ia-fast-jump)
(local-set-key "\C-cr" 'semantic-symref-symbol)
(local-set-key "\C-cR" 'semantic-symref)
;;; c/c++ setting
(local-set-key "." 'semantic-complete-self-insert)
(local-set-key ">" 'semantic-complete-self-insert))
(add-hook 'c-mode-common-hook 'my-cedet-hook)
现在我们可以写个测试程序
mkdir ~/test_code
cd ~/test_code
C-x C-f 创建t1.c
内容如下:
#include <stdio.h>
int main() {
FILE *fp;
fp->
}
当按下>键后会在另一个buffer中现实自动补全的内容,如下图:
系统目录头文件、标准库补全都可以了,可以写个c++文件测试下STL的补全也是可以的了,如图:
另外还包括所编辑文件中和所编辑文件所在的当前目录下的头文件都可以自动解析补全了。
2、项目自定义头文件补全
首先我们先创建多个目录程序,模拟实际项目,~/test_code为我们项目所在目录
cd ~/test_code
mkdir common fun_a
创建文件common/common.h内容如下:
#ifndef COMMON_H_
#define COMMON_H_
struct common {
int id_common;
char str_common[128];
};
#endif /* COMMON_H_ */
创建文件fun_a/fun_a.h内容如下:
#ifndef FUN_A_H_
#define FUN_A_H_
struct fun_a {
int id_a;
char name_a[128];
};
#endif /* FUN_A_H_ */
创建文件main.c:
#include <stdio.h>
#include "common.h"
#include "fun_a.h"
int main() {
struct common com;
struct fun_a fa;
com.
}
此时发现并没有出现补全的buffer,如图:
可以看到
#include "common.h"
#include "fun_a.h"
这两行为红底,表示为semantic找不到这两个头文件,也可以用菜单 Senator -> Analyze -> Sumarry includes current buffer看到Unknow includes有两项。
项目自定义头文件的补全关键是要让semantic能够找到我们定义的头文件在哪儿然后让semantic解析,告诉semantic我们自定头文件的目录有好几种办法:
(1) 把光标移动到红底的#include行上时,会出现Unknow Include菜单,可以选其下Add a system include path项,分别将common、fun_a两个目录添加进去,然后再选菜单[Senator -> Force Tag Refresh]或用快捷键C-c ,,,刷新Tag即可,#include那两行随之变色,然后输入com.后即可出现补全buffer。
(2) 在.emacs中用semantic-add-system-include函数添加需要解析的头文件的目录,例如:
(require 'semantic-c nil 'noerror)
(semantic-add-system-include "~/test_code/common" 'c-mode)
(semantic-add-system-include "~/test_code/fun_a" 'c-mode)
注意,(require 'semantic-c nil 'noerror)这行是必须的,否则semantic不会去找我们配置的路径,原因可参考用CEDET浏览和编辑C++代码,现在已经可以解析、补全我们在common、fun_a目录中定义的头文件了,但是在.emacs中配置的semantic-add-system-include路径必须是全路径,而不能是相对路径,这点上可能和用CEDET浏览和编辑C++代码这篇文章有出入,大家可以去测试一下。故,我们需要第三种方法,能根据不同的项目去解析各个项目的头文件。
(3) 第三种方法就是用CEDET里的EDE,分别给每个项目设置root目录,然后可根据root目录的相对路径配置头文件路径。
比如,可以在.emacs中配置我们项目的目录:
(setq cpp-test_code-project
(ede-cpp-root-project "test_code"
:file "~/test_code/main.c"
:include-path '("/common"
"/fun_a")))
其中的:file相为项目等层目录,即项目root目录的一个文件,随便哪个文件都可以,这只是一个标识。
这样就可以就可以解析了。
可能有人觉得这样要在.emacs中配置很麻烦,其实也可以在项目的root目录下建立一个文件proj.el,内容如下:
(setq cpp-test_code-project
(ede-cpp-root-project "test_code"
:file "~/test_code/main.c"
:include-path '("/common"
"/fun_a")))
在每次编辑项目的时候执行:
M-x load-file
proj.el
即可,相当于“打开项目”吧 :)
其实EDE的功能很强大,可以像现代IDE一样管理、构建整个项目,可参考EDE文档,如果所在项目组的人都用emacs,还真可以考虑下用EDE :)
OK, 有这几种方法告诉semantic解析的头文件路径,补全就基本没有什么问题了,semantic的补全很智能,不会给你补些乱七八糟的东西。 semantic第一次补全需要解析头文件,所以很慢,不过以后就会很快了。如果semantic突然不能补全了,可以删掉semanticdb下的东西 试试,一般可以用命令:
rm -rf ~/.semanticdb ~/.srecode
Good Luck :)
(转载时请注明作者和出处。未经许可,请勿用于商业用途)