vimでRSenseの補完ができない件で悩んでいたけどとりあえず解決できた

環境はWinXP/香り屋さんのvim7.3/RSense3.0/Ruby 1.9.3です。
RSenseをセットアップして、vimからRSenseVersionできるのに、補完が効かない。
C-x C-o でオムニ補完すると、「パターンは見つかりませんでした」と出る。

実は2週間だらだらとできないなーと悩んでいたのですが、腰を据えてトラシューしてみたら、原因が判明して、動作するようにできた。

状況の整理

    • vimからRSenseVersionするとちゃんと3.0と表示される
    • vimからRSenseServiceStartとかRSenseServiceStopができてる
    • %RSense_HOME%/rsense-service.logを見ると、vimから補完したタイミングでログ出力されているが、特にエラーっぽいログは見当たらない
    • だけど、オムニ補完(C-x C-o)すると「パターンは見つかりませんでした」といわれてしまう

調べたこと

ログは次のように出ているわけです

recv: code-completion --file=C:\DOCUME~1\ZZTSAS~1\LOCALS~1\Temp\VID331.tmp --location=5:5 --prefix= --detect-project=test.rb

test.rb

# RSense completion test

def test
	str = "testdesu"
	str.
end

str.まで打って、オムニ補完した。
その結果

で、vim->RSenseへの処理を調べてみた。この時点ではvimからRSenseに補完のリクエストが出ているけど、受け取るときとかに問題が出ているのではないかと予想

vimスクリプトよく知らないけど、眺めてみた。

オムニ補完すると、rsense.vim の RSenseCompleteFunction が呼ばれるらしいのでそこを見る

function! RSenseCompleteFunction(findstart, base)
    if a:findstart
        let cur_text = strpart(getline('.'), 0, col('.') - 1)
        return match(cur_text, '[^\.:]*$')
    else
        let result = split(s:rsenseCommand(['code-completion',
                                            \ s:rsenseCurrentBufferFileOption(),
                                            \ s:rsenseCurrentLocationOption(),
                                            \ '--prefix=' . a:base]),
                           \ "\n")

となっていて、rsenseCommand を呼び出している。

function! s:rsenseCommand(args)
    for i in range(0, len(a:args) - 1)
        let a:args[i] = shellescape(a:args[i])
    endfor
    return s:system(printf('ruby %s %s %s',
                           \ shellescape(s:rsenseProgram()),
                           \ join(a:args, ' '),
                           \ shellescape('--detect-project=' . bufname('%'))))

これをみると、s:system でコマンド実行しているようだ。
ということは、ログに出ていたのはこの部分で、コマンド実行されているだけってことか。ということで、ログの出力の先頭にs:rsenseProgramから戻ってくる結果をくっつけて、%RSense_HOME%で実行してみた

FileNotFoundException とは。。。
そして、エラーメッセージのファイル名に「¥」が無い。。。そうか!!エスケープシーケンスが悪さしているんじゃね?

で、コマンドラインをちょっと細工(¥→¥¥に。RSenseはJavaだからねー)

おー。補完されてるっぽい!

ということで、rsense.vimに細工
ぐぐると文字列の置換はsubstituteを使えばいいっぽい。
http://route477.net/w/?VimScriptMemo

--- C:/Program Files/vim73-kaoriya-win32/vim73/plugin/rsense.vim.original	Tue Sep 25 23:14:19 2012
+++ C:/Program Files/vim73-kaoriya-win32/vim73/plugin/rsense.vim	Sat Sep 29 05:00:41 2012
@@ -37,7 +37,7 @@
 
 function! s:rsenseCurrentBufferFile()
     let buf = getline(1, '$')
-    let file = tempname()
+    let file = substitute(tempname(), "\\", '\\\\', 'g')
     call writefile(buf, file)
     return file
 endfunction

これで補完ができるようになった。

やっとできて、すっきりしました~

いやーRSenseステキ〜!!vimステキ〜!!