作者:winterTTr 轉載請註明
我想,很多人都希望能夠在vim或者emacs中實現C++的自動補全,我個人也不例外。
折騰過ctags,etags,cscope,最後也折騰過cedet。說實話,cedet還是可以實現補全的,只是速度有點讓人難以忍受。
上面的幾種工具,都是通過對原始碼進行預先處理,分析出其包含的代碼資訊。但是,大部分程式都是通過靜態分析代碼,這點在代碼或者標頭檔頻繁變更的情況下,是非常讓人頭痛的事情。像Visual Stuido中代碼補全功能,基本上全是動態,當標頭檔發生變化後,補全也會馬上跟著變化。
我們是否也能實現這樣的功能呢?
在clang這個llvm的C++前端出現之前,或許只能說遺憾了。靜態ctags補全必須完全掃描所有的檔案,這樣的效率是不可以接受的。
不過現在有了clang,這為我們系提供了非常好的工具,來實現這個願望。
準備工作
1. 不用說了,肯定是需要clang了。
clang需要自己編譯。由於我使用的是windows,所以,這裡有一個我自己編譯的版本。
https://github.com/winterTTr/emacs-of-winterTTr/tree/master/.emacs.d/extra-bin/clang
有關環境的設定,可以參考上篇文章。
[plain]
view plaincopyprint?
- (wttr/prepend-to-exec-path "~/.emacs.d/extra-bin/clang")
(wttr/prepend-to-exec-path "~/.emacs.d/extra-bin/clang")
2. auto-complete和auto-complete-clang.el
auto-complete是一個非常好用的emacs擴充,而auto-complete-clang就是在這個擴充的基礎上完成的。所以兩者必須同時安裝:
這裡是我現在正在使用的auto-complete擴充,已經包含了clang。
https://github.com/winterTTr/emacs-of-winterTTr/tree/master/.emacs.d/plugins/auto-complete-1.3.1
配置
首先是載入auto-complete擴充:
[plain]
view plaincopyprint?
- ;; 載入auto-complete
- (wttr/prepend-to-load-path "~/.emacs.d/plugins/auto-complete-1.3.1")
- (require 'pos-tip)
- (require 'auto-complete)
- (require 'auto-complete-config)
- (add-to-list 'ac-dictionary-directories "~/.emacs.d/plugins/auto-complete-1.3.1/dict")
- (ac-config-default)
-
- (global-auto-complete-mode t)
-
- ;; 使用Ctrl+enter按鍵觸發自動補全
- (define-key ac-mode-map [(control return)] 'auto-complete)
;; 載入auto-complete(wttr/prepend-to-load-path "~/.emacs.d/plugins/auto-complete-1.3.1")(require 'pos-tip)(require 'auto-complete)(require 'auto-complete-config)(add-to-list 'ac-dictionary-directories "~/.emacs.d/plugins/auto-complete-1.3.1/dict")(ac-config-default)(global-auto-complete-mode t);; 使用Ctrl+enter按鍵觸發自動補全(define-key ac-mode-map [(control return)] 'auto-complete)
下面設定auto-complete-clang
[plain]
view plaincopyprint?
- ;; 載入clang
- (require 'auto-complete-clang)
-
- ;; 添加c-mode和c++-mode的hook,開啟auto-complete的clang擴充
- (defun wttr/ac-cc-mode-setup ()
- (make-local-variable 'ac-auto-start)
- (setq ac-auto-start nil) ;auto complete using clang is CPU sensitive
- (setq ac-sources (append '(ac-source-clang ac-source-yasnippet) ac-sources)))
- (add-hook 'c-mode-hook 'wttr/ac-cc-mode-setup)
- (add-hook 'c++-mode-hook 'wttr/ac-cc-mode-setup)
;; 載入clang(require 'auto-complete-clang);; 添加c-mode和c++-mode的hook,開啟auto-complete的clang擴充(defun wttr/ac-cc-mode-setup () (make-local-variable 'ac-auto-start) (setq ac-auto-start nil) ;auto complete using clang is CPU sensitive (setq ac-sources (append '(ac-source-clang ac-source-yasnippet) ac-sources)))(add-hook 'c-mode-hook 'wttr/ac-cc-mode-setup)(add-hook 'c++-mode-hook 'wttr/ac-cc-mode-setup)
添加系統標頭檔的目錄,這點非常重要,clang就是通過ac-clang-flags這個變數中的設定,來正確找到所有的系統標頭檔的。
但是請注意,不是添加標頭檔,是添加標頭檔的*目錄*。
其實,這個變數就是命令列中clang所能接受的參數,-IPath代表include這個Path路徑作為系統標頭檔路徑。-DSome表示定義Some這個宏。
我想使用過gcc的人都瞭解,這個是編譯器的命令列參數。
我使用windows下的mingw的標頭檔路徑,所以設定如下:
[plain]
view plaincopyprint?
- (setq ac-clang-flags (list
- "-IC:/MinGW/include"
- "-IC:/MinGW/lib/gcc/mingw32/4.6.1/include"
- "-IC:/MinGW/lib/gcc/mingw32/4.6.1/include/c++"
- "-IC:/MinGW/lib/gcc/mingw32/4.6.1/include/c++/mingw32"
- "-D__MSVCRT__="))
(setq ac-clang-flags (list "-IC:/MinGW/include" "-IC:/MinGW/lib/gcc/mingw32/4.6.1/include" "-IC:/MinGW/lib/gcc/mingw32/4.6.1/include/c++" "-IC:/MinGW/lib/gcc/mingw32/4.6.1/include/c++/mingw32" "-D__MSVCRT__="))
好了,現在開啟一個test.cpp檔案可以試一下,由於我的設定,補全通過ctrl-enter觸發。
不止能補全函數,還能補全參數,auto-complete是個非常好的架構。
PS:
wttr開頭是所有的函數,是我自己定義的,可以參考這裡。
https://github.com/winterTTr/emacs-of-winterTTr/blob/master/.emacs.d/wttr-config/wttr-utils.el