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


こないだは、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が正常動作しなくなる可能性もあります。ま、ただ読んでいるだけなのでそんなことはないとは思いますが、ということで、使う場合は自己責任にてお願いします。おかしな点とかも教えてもらえるとうれしいです。

  • sirioyaji

    大変有用で効率があがりました。有難うございます。
    ただ、数字まで補完機能が効いてしまうので、margins=1と入力したいときに、データを表示した時などの影響?で思った数字が入力できなくて困る時があります。
    できれば改善できませんか?

    PS
    語彙辞書?は~/hoge のUSR_LIBから私がもっともよく使う vcdなどを追加して便利に使わせてもらっています。私のような素人でも分かるありがたい仕様です。

    • myuhe

      >> sirioyajiさん
       コメントありがとうございます。
       ご要望の件、ちょっと現象を理解できないのですが、憶測も交えてお答えすると、emacs標準のdabbrevがきいてそのようになるのだと思います。
       説明には書いてなかったのですが、補完候補は、namespaceから取ってきた関数群(abbrev)と同一バッファ内の関数から取ってくるdabbrevで構成されていて、最初にdabbrevの候補が表示されるようになっています。dabbrevの方は、auto-complete.el標準の機能であって、改良するとなるとエセlisperの私には荷が重そうですし、むしろauto-complete.elの作者の方にお願いした方が良いかもしれません。

       というわけで、あくまで暫定的な対処法を二つあげます。
      1.dabbrev解除
      http://github.com/myuhe/auto-complete-acr.el/blob/1a8fab97e21fd81bc1bb904c07220384afcb9ca7/auto-complete-acr.el
      の396,403行目にあるac-source-words-in-bufferを削除すれば、dabbrevはキャンセルでき、お尋ねの現象もなくなるかもしれません。そのかわりdabbrevの補完候補はでてきません。

      2.関数の後にスペースを入れる癖をつける。
       このように書くことで、その現象自体起きないような気がします。
       ただ、こちら(winXP,meadow)で試してみたところ、hogehoge=1のように書いてもそのような現象は起きませんでした。ですので、もしかしたら別の原因があるかもしれません。

      根本的解決ではないですが、お試しください。

  • sirioyaji

    大変有用で効率があがりました。有難うございます。
    ただ、数字まで補完機能が効いてしまうので、margins=1と入力したいときに、データを表示した時などの影響?で思った数字が入力できなくて困る時があります。
    できれば改善できませんか?

    PS
    語彙辞書?は~/hoge のUSR_LIBから私がもっともよく使う vcdなどを追加して便利に使わせてもらっています。私のような素人でも分かるありがたい仕様です。

  • myuhe

    >> sirioyajiさん
     コメントありがとうございます。
     ご要望の件、ちょっと現象を理解できないのですが、憶測も交えてお答えすると、emacs標準のdabbrevがきいてそのようになるのだと思います。
     説明には書いてなかったのですが、補完候補は、namespaceから取ってきた関数群(abbrev)と同一バッファ内の関数から取ってくるdabbrevで構成されていて、最初にdabbrevの候補が表示されるようになっています。dabbrevの方は、auto-complete.el標準の機能であって、改良するとなるとエセlisperの私には荷が重そうですし、むしろauto-complete.elの作者の方にお願いした方が良いかもしれません。

     というわけで、あくまで暫定的な対処法を二つあげます。
    1.dabbrev解除
    http://github.com/myuhe/auto-complete-acr.el/bl

    2.関数の後にスペースを入れる癖をつける。
     このように、書くことでその現象自体起きないと思います。ちなみに私は、元々そのように書いていたので、お尋ねのような現象には気づきませんでした。また、そういう書き方の方が、変なバグなどを回避できるように思います。

    根本的解決ではないですが。お試しください。

  • sirioyaji

    大変有用で効率があがりました。有難うございます。
    ただ、数字まで補完機能が効いてしまうので、margins=1と入力したいときに、データを表示した時などの影響?で思った数字が入力できなくて困る時があります。
    できれば改善できませんか?

    PS
    語彙辞書?は~/hoge のUSR_LIBから私がもっともよく使う vcdなどを追加して便利に使わせてもらっています。私のような素人でも分かるありがたい仕様です。

  • myuhe

    >> sirioyajiさん
     コメントありがとうございます。
     ご要望の件、ちょっと現象を理解できないのですが、憶測も交えてお答えすると、emacs標準のdabbrevがきいてそのようになるのだと思います。
     説明には書いてなかったのですが、補完候補は、namespaceから取ってきた関数群(abbrev)と同一バッファ内の関数から取ってくるdabbrevで構成されていて、最初にdabbrevの候補が表示されるようになっています。dabbrevの方は、auto-complete.el標準の機能であって、改良するとなるとエセlisperの私には荷が重そうですし、むしろauto-complete.elの作者の方にお願いした方が良いかもしれません。

     というわけで、あくまで暫定的な対処法を二つあげます。
    1.dabbrev解除
    http://github.com/myuhe/auto-complete-acr.el/bl
    の396,403行目にあるac-source-words-in-bufferを削除すれば、dabbrevはキャンセルでき、お尋ねの現象もなくなるかもしれません。そのかわりdabbrevの補完候補はでてきません。

    2.関数の後にスペースを入れる癖をつける。
     このように書くことで、その現象自体起きないような気がします。
     ただ、こちら(winXP,meadow)で試してみたところ、hogehoge=1のように書いてもそのような現象は起きませんでした。ですので、もしかしたら別の原因があるかもしれません。

    根本的解決ではないですが、お試しください。

  • Pingback: ESS on Emacsで快適に補完できるauto-complete-acr.el0.2リリースしました()