読者です 読者をやめる 読者になる 読者になる

理科系の備忘録

Linux/Ubuntu/Mac/Emacs/Computer vision/Robotics

auto-complete-clang

設定 Emacs

auto-complete.elはEmacsで補完候補を提示してくれるパッケージである.
バッファに登場している文字列を候補として出してくれるというものであるが,VisualStudioやEclipseのように関数の候補などを提示することはできない.


▲auto-completeによって候補が示されている


しかし,auto-complete-clang.elによって,Emacsでも同様のことが可能となる.


clnagとはmacの支援する現在開発中のコンパイラであり,今後gccにかわる新しいコンパイラとなる可能性がある.
http://ja.wikipedia.org/wiki/Clang
macには標準でインストールされているためインストールする必要はなかったが,環境によってはインストールが必要となる.

clangによる補完機能を試すため,以下のようなソースコードを作って動作を確認した.

#include <iostream>
#include <vector>

int main(){

  int hoge1, hoge2;

  for(int i=0; i<100; i++){
    std::vector<int> v;
    v.
  }
}

10行目がドットで終わっていることに注目してほしい.clangがvectorメンバ関数候補を示してくれるはずである.
以下のコマンドをターミナルに入力する.

clang -cc1 -fsyntax-only -code-completion-at=hoge.cpp:7:7 hoge.cpp

すると次のような結果を得た.

...

COMPLETION: operator[] : [#reference#]operator[](<#size_type __n#>)
COMPLETION: operator[] : [#const_reference#]operator[](<#size_type __n#>)[# const#]
COMPLETION: pop_back : [#void#]pop_back()
COMPLETION: push_back : [#void#]push_back(<#const value_type &__x#>)
COMPLETION: rbegin : [#reverse_iterator#]rbegin()

...

v.push_back()やv.pop_back()が候補として登場していることがわかる.
これをauto_completeと同様に表示させようというものがauto-complete-clangである.

環境を構築するために,まずはato-complete-clang.elを用意して,load-pathの通っている場所へ置く.
次に以下を.emacsに記述した.

;;elisp load-path
(setq load-path
      (append
       (list
	(expand-file-name "~/site-lisp/")
	)
       load-path))

;; ...
;; 中略
;; ...

;; auto-complete-clang 設定
(require 'auto-complete-config)
(require 'auto-complete-clang)
;; (ac-config-default)

;;補完キー指定
(ac-set-trigger-key "TAB")
;;ヘルプ画面が出るまでの時間(秒)
(setq ac-quick-help-delay 0.8)

(defun my-ac-cc-mode-setup ()
  ;;tなら自動で補完画面がでる.nilなら補完キーによって出る
  (setq ac-auto-start nil)
  (setq ac-clang-prefix-header "~/site-lisp/stdafx.pch")
  (setq ac-clang-flags '("-w" "-ferror-limit" "1"))
  (setq ac-sources (append '(ac-source-clang 
			     ac-source-yasnippet 
			     ac-source-gtags)
			   ac-sources)))

(defun my-ac-config ()
  (global-set-key "\M-/" 'ac-start)
  ;; C-n/C-p で候補を選択
  (define-key ac-complete-mode-map "\C-n" 'ac-next)
  (define-key ac-complete-mode-map "\C-p" 'ac-previous)

  (setq-default ac-sources '(ac-source-abbrev 
			     ac-source-dictionary 
			     ac-source-words-in-same-mode-buffers))
  (add-hook 'c++-mode-hook 'ac-cc-mode-setup)
  (add-hook 'emacs-lisp-mode-hook 'ac-emacs-lisp-mode-setup)
  (add-hook 'c-mode-common-hook 'my-ac-cc-mode-setup)
  (add-hook 'ruby-mode-hook 'ac-css-mode-setup)
  (add-hook 'auto-complete-mode-hook 'ac-common-setup)
  (global-auto-complete-mode t))

(my-ac-config)

途中に出てくる

(setq ac-clang-prefix-header "~/site-lisp/stdafx.pch")

は,ヘッダファイルをプリコンパイルしたものを使用することを意味している.
これを指定しないと,候補を出すたびにclangを実行することになり非常にもっさりとしてしまう.
stdafx.pchの作り方は以下の通り.

// stdafx.hpp

#include <iostream>
#include <vector>

上記のようなstdafx.hppを作り,以下のコマンドでコンパイルをする.

clang++ -cc1 -emit-pch -x c++-header ./stdafx.hpp -o stdafx.pch

生成したpchファイルを(setq ac-clang-prefix-header "./site-lisp/stdafx.pch")に書いた場所に置けばOK.普段使いそうなものをあらかじめコンパイルしておくと便利である.OpenCVなど外部のライブラリをコンパイルする際は,gccと同様のオプションである-Iをつければよい.

clang++ -cc1 -emit-pch -x c++-header ./stdafx.hpp -o stdafx.pch -I/opt/local/opencv/include/

もちろん

clang++ -cc1 -emit-pch -x c++-header ./stdafx.hpp -o stdafx.pch `pkg-config --cflags opencv`

でもいける.

実際にEmacsを起動して試してみたものが下図となる.
auto-completeだけでも十分便利だが,clangによるスマートな補完によってさらにEmacsが便利になった.



▲バッファに登場していない文字列だが,候補として表示されている.