CEDET是emacs非常強大的一個擴充,已經被包含在gnu emacs中,代碼補全是個很方便的功能,已經有很多文章介紹過這方面的了,其中算最全面的是
- A Gentle introduction to Cedet
- 用CEDET瀏覽和編輯C++代碼
- 用CEDET瀏覽和編輯C++代碼(續) – 使用Emacs 23.2內建的CEDET
這三篇文章已經詳細介紹了如何使用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
(轉載時請註明作者和出處。未經許可,請勿用於商業用途)