vimでvim-quickrunというプラグインを使ってRustコンパイルする設定をしていた時、つまづいたところがあったんですが、 他に情報が載っていなかったので、メモします。

起きた問題

vim-quickrunは、vimのコマンドラインモードで:QuickRunと打ち込むだけで任意のプログラムを実行し、結果を表示してくれる便利なプラグインです。
デフォルトでRustに対応しており、filetypeがRustの時はrustcでコンパイルした結果を表示してくれるはずでした。
しかし、以下のようなエラーが表示されてしまいました。

'"D:\Documents\rust-test\hello_world\src\main"' は、内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されていません。

結論

g:quickrun_configに以下のように記せば良いことがわかりました。

    let g:quickrun_config = {
    \   'rust': {
    \       'exec': ['%c %o %s', '%s:p:r %a'],
    \       'tempfile': 'tmp.rs',
    \       'hook/sweep/files': ['%S:p:r', '%S:p:r.pdb', '%S:p:r.exe', 'tmp.pdb' ,'tmp.exe'],
    \   },
    \ }

検証

QuickRunは、デフォルトのquickrun_configで、Rustを以下のように実行するよう設定されています

let g:quickrun_config = {
\ 'rust': { 
\   'command': 'rustc', 
\   'exec': ['%c %o %s -o %s:p:r', '%s:p:r %a'], 
\   'tempfile': '%{tempname()}.rs', 
\   'hook/shebang/enable': 0, 
\   'hook/sweep/files': '%S:p:r', 
\ },

では、これがどのように実行されているのか。
QuickRunにはデバッグ機能があるそうで、:QuickRun -debug aとやると変数aに結果が保存されます。
そして、echo g:a.commandsとやると、以下のように実行されたことがわかります。

'"C:\Users\isudzumi\.cargo\bin\rustc.EXE"  "D:\Documents\rust-test\hello_world\src\main.rs" -o "D:\Documents\rust-test\hello_world\src\main"', '"D:\Documents\rust-test\hello_world\src\main" ']

-oで指定されているところがポイントになります。
rustcでも、gccなどと同様、-oオプションは出力ファイル名を指定します。
しかし、拡張子も指定しないといけないという制約があります。
試しにrustc main.rs -o mainと実行すると、拡張子なしのmainという実行ファイルが生成されます。
ここが問題だったんですね。
つまり、g:quickrun_config

'rust': {
    'exec': ['%c %o %s -o %s:p:r.exe', '%s:p:r %a'],
}

としてやれば良いわけです。
ただ、これだとWindowsでしか実行できません。
rustcでは、-oオプションを指定しなくても、ソースファイルと同じ名前の実行ファイルを生成してくれます。
そこで、-o自体を取ってしまいました。

'rust': {
    'exec': ['%c %o %s', '%s:p:r %a'],
}

言うのを忘れていましたが、ここで使っているrustcのバージョンは1.24.1です。
じゃあこれで出来たかというと、まだ終わりではありませんでした。
これを:wで保存せずに実行すると、以下のようなエラーが表示されます。

error: invalid character `.` in crate name: `VIG2253.tmp`

error: aborting due to previous error

要はソースファイル名に.が含まれているから怒られたわけです。
デバッグ結果は以下になります。

'"C:\Users\isudzumi\.cargo\bin\rustc.EXE"  "C:\Users\isudzumi\AppData\Local\Temp\VIG2253.tmp.rs"',
'"C:\Users\isudzumi\AppData\Local\Temp\VIG2253.tmp" ']

QuickRunはソースファイルを保存せすに実行する際、tempファイルを作成します。
これがデフォルトでは.を含むため、こうしたエラーが出てしまいました。
デフォルトの%{tempname()}のままではどうしても解決できないので、

'rust': {
    'tempfile': 'tmp.rs',
}

という風に、tempファイルの名前を決めてしまいました。
こうすると、tmp.pdbtmp.exeが生成され、tmp.exeの実行結果が表示されます。
tempファイルが残るのはちょっと汚いので、以下の設定を追加し、実行後に生成されたファイルが消えるようにしました。

'rust': {
   'hook/sweep/files': ['%S:p:r', %S:p:r.pdb', '%S:p:r.exe', 'tmp.pdb' ,'tmp.exe']
}

これで想定通りに動くようになりました。

このエントリーをはてなブックマークに追加