続 auto-complete-clang

どもです。
風邪がだいぶ楽になってきて幸せをかみしめています。
てか,明日の最高気温と最低気温が6度って(東京ね)。
また風邪ひくんちゃうかぁ。


最初に言っておきますが,以下のことをしてもそれほど実用的にはならんと思います。
自分でやっておいてなんですが。
過程が大事なんです,過程が。と,自分に言い聞かせています。

ちょっと頑張ってみた

人生初の YouTube への投稿。gif アニメを作成するのが面倒だったし。。。

まず,pch を作成した。

stl.hh というファイルを,下記の内容で作成。

#include <algorithm>
#include <bitset>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <typeinfo>
#include <utility>
#include <vector>

ほいで,プリコンパイルヘッダ(日本語はこれであってるのだろうか?) を作成します。

% clang -cc1 -x c++-header ./stl.hh -emit-pch -o stl.hh.pch

brianjcj さん作成の auto-complete-clang.el を使用するという前提で話を進めます。
ac-clang-set-prefix-header という interactive な関数が用意されているので,
M-x ac-clang-set-prefix-header して,先ほど作成した pch を指定します。
これで,pch を使えるなら使って補完してくれるはずです。
けど,複数の pch を使用したい場合とかは困るので,リストで管理してくれるとうれしいな。
etags みたいに。

だが,しかし・・・。

自動補完にしておくと,1文字入力しただけで,ac-source-clang による補完が
始まります。(デフォルトのままだとね)
これは困ります。


なので,ソースに手を入れて,下記の条件の時に ac-source-clang による補完が
発動するようにしてみた。
その条件は,現在のポイントと backward な方向にある最初のスペース(ない場合は,行頭)
の間に「<」,「.」,「->」,「::」,がある,もしくは,
入力文字が,「.」,「->」,「::」である,というもの。
こうして,発動条件を絞ることで,自動補完にしておいても,くるしゅーない。
以下,diff。

--- auto-complete-clang.el	2011/03/06 04:04:52	1.1
+++ auto-complete-clang.el	2011/03/06 12:57:09
@@ -243,8 +243,20 @@
       (unless (cdr candidates) ;; unless length > 1
         (message (replace-regexp-in-string "\n" "   ;    " help))))))
 
+(defun ac-clang-prefix-symbol ()
+  "Return the result of (ac-prefix-symbol) if there is a `<' or `.' or
+`->' or `::' between current point and the nearest space or tab
+backward."
+  (let ((p (or (save-excursion
+                 (re-search-backward "[ \t]"
+                                     (save-excursion (beginning-of-line) (point))
+                                     t))
+               (save-excursion (beginning-of-line) (point)))))
+    (when (save-excursion (re-search-backward "<\\|\\.\\|->\\|::" p t))
+      (ac-prefix-symbol))))
+
 (defun ac-clang-prefix ()
-  (or (ac-prefix-symbol)
+  (or (ac-clang-prefix-symbol)
       (let ((c (char-before)))
         (when (or (eq ?\. c)
                   ;; ->

あと,ソースがかなり読みやすかった気がします。
勉強になります。


ほいで,以上2つのことを使ったデモが,最初の動画です。

まとめ

ぶっちゃけ,これでも,デカイソースとかだと使い物にならんと思います。
というわけで,まとめると,やっぱりトリガーキーを設定して,
補完するのがいいかなぁというオチです。

その他。

vim の clang_complete が,libclang をどうやって使っているのか知りたくて,
ソースを眺めてみた。前回よりは少し分かった気がする。
どうやら,libclang を python から使えるのがあって,
そいつを使って,補完をしている感じ?
そうすると,毎回 clang を呼ばなくて,自前でキャッシュとか管理すればいいので,
早くなるという感じかな?
確かに,補完目的で,毎回ヘッダなりをパースするのは,変更が加わらない限り無駄だしね。
ほいで,最初から用意されているヘッダ,例えば,vector とかは,外部から使う分には,
変更するこたーないと。
いや,書いていて思ったが,そんなことはないのか。入力は刻一刻と変わるので,
補完対象を決めるのには毎回パースする必要があるのか。
とすると,どうして早くなるんだろう。。。
ま,いいや。
あれ? ということはさぁ,emacs からでも使えるんじゃね?
誰か作ってくれないかなぁ。


細かい設定(色とか,候補数の制限とか)をやっていないので,
それらをやる必要があるわけで,たぶん続く。はず。きっと。おそらく。もしかしたら。


最後に作者の人達にありがとう!