auto-complete.elを拡張するR用のelispをさらに拡張してみた。

NO IMAGE

こないだは、auto-complete.elを拡張するR用のelispをさらに拡張するelispとしてauto-complete-acr.elを書いてみたわけですが、前回のバージョンだとnamespace:statsな関数群しか補完できないというショボショボバージョンでした。

なぜさらに拡張する必要があるのか

例えばapply系とlibrary()などは頻用する関数ですし、library(grid)とか常用される方は、あの長たらしい関数名を補完したいなーという欲求が少なからずあると思います。ですが、現状では、namespace:statsな関数しか補完できません。また、Rの自由度の高さ故どんなパッケージを入れていて、どんな関数を使っているかというのは人それぞれなわけで、できれば個人個人の環境に合わせた補完ライブラリを作るのがベターと考えました。というわけで、今回は任意にインストールしたパッケージの関数群も含めて全ての関数の補完ライブラリを生成するpythonスクリプトを書いてみました。

いつものごとく、githubにソースコード諸々あげてます。auto-complete-acr.elも今回のスクリプトを反映したものにバージョンをあげていますので、ご自由にお使いください。

スクリプトの仕組み

Rの中身をいろいろと眺めてみた結果、全ての関数群はNAMESPACEというファイルで管理されているようです(namespace:base以外)。これで管理することで名前の衝突を回避している模様(ref:私的パッケージ作成法 – RjpWiki)。
ということは、全てのNAMESPACEファイルの中から関数を定義している部分を抽出してあげれば補完候補のライブラリができるはずです。これはNAMESPACEファイルではexport()にあたります。というわけで、このような方針でスクリプトに落としていきます。

NAMESPACE:baseの関数だけは別格で、それぞれの関数が一つのファイルとして管理されているので、これは別のルーチンにして書きます。

使い方

スクリプトは、これです。

[python]
import os
import re

filenamelist=[]

for dpath,dname,filename in os.walk("/usr/lib/R/library"):
for filename in filename:
if filename == ("NAMESPACE"):
fpath = os.path.join(dpath,filename)
filenamelist.append(fpath)

mer=[]

for file__ in filenamelist:
f = open(file__)

p1 = re.compile(‘export(‘)
frag = 0
strfrag = 0

for line in f:
if line[0:7] == ‘export(‘ and ")" not in line:
frag = 1
line = line.strip()
line = p1.sub("",line)
mer.append(line)

elif line[0:7] == ‘export(‘ and ")" in line:
frag= 0
line = line.strip()
line = re.sub(")",",",line)
line = p1.sub("",line)
mer.append(line)

elif frag == 1 and ")" not in line and "#" not in line:
line = line.strip()
mer.append(line)

elif frag == 1 and ")" in line and "#" not in line:
frag = 0
line = line.strip()
line = re.sub(")",",",line)
mer.append(line)

elif frag == 1 and ")" not in line and "#" in line:
frag = 1

elif frag == 1 and ")" in line and "#" in line:
frag = 1

else:
frag = 0

out = "".join(mer)
out = re.sub(" ","",out)
out = re.sub(‘"’,"",out)
out = re.sub(",","" "",out)
out = re.sub("^""",’"’,out)
out = re.sub("$""",’"’,out)

print out
[/python]

ちなみに当方の環境はubuntu9.04です。動かすにはpython実行環境をインストールしている必要があります。Linux,Macなら多くはデフォルトで入っているはずですが、WinではActive python等を自前でインストールする必要があります。スクリプト自体はOSに依存しないように書いている(つもり)ので、どの環境でも使えるはずです。
使い方はとっても簡単。NAMESPACEファイルがあるディレクトリかそれを含む親ディレクトリを6行目で指定してあげて実行すれば、補完候補がずらーっと出てくるはずです。ここで、一番浅いディレクトリを指定すれば、追加してインストールしたパッケージも含め、全ての関数の補完候補が出てくるはずです。そんなのしたら候補が多くなって面倒、という方は適宜深いディレクトリを指定すれば、そのディレクトリ以下の関数群だけ取ってきてくれます。

NAMESPACE:baseの分はこちら。これは、Linux環境の場合は特に修正しなくてもいけるはずです。

[python]
import os
import re

file =os.listdir("/usr/lib/R/library/base/R-ex")
file.sort(lambda x,y:cmp(x,y))

out= ‘" "’.join(file)
out = re.sub(".R","",out)
out = re.sub("^",’"’,out)
out = re.sub("$",’"’,out)
print out
[/python]

後はauto-complete-acr.elで関数を定義しているところにコピペすればオリジナルauto-complete-acr.elの完成です。

現状の問題点、とお願い

これで、個人的には満足できるツールになりました。ただ、補完ライブラリを作って後からなんかのパッケージをインストールした場合、そいつの関数群は反映されません。というか、pythonで吐き出したテキストをelispにコピペというのはかなりださい・・・と言ってもlispを本格的に勉強する気にもなれないので、どなたかelispに移植してくれる方募集中です。それとubuntu9.04でしか動作を確認していません。他の環境で試された方は、動作報告してもらえるとうれしいです。動かんぞ!!な苦情もよろしくお願いします。
それと、スクリプト自体に問題があるかもしれません。特にNAMESPACEファイルを壊してしまったりすると、Rが正常動作しなくなる可能性もあります。ま、ただ読んでいるだけなのでそんなことはないとは思いますが、ということで、使う場合は自己責任にてお願いします。おかしな点とかも教えてもらえるとうれしいです。