Humanity

Edit the world by your favorite way

Vimを常駐化してファイルの読み込みを爆速化する

ばよえ〜ん(訳:Vim Advent Calendar 2012への16回目の投稿です)
この記事はVim Advent Calendar 2012の150日目の埋め合わせ記事になります。
149日目は@manga_osyoさんでneobundle.vim で github の C++ ライブラリを管理するでした。

履歴

  • FAQ Q3のコードを修正。(guioptionsを手動でいじる場合、FocusGainedイベント時に常にguioptionsがリセットされてしまう)
  • id:thincaさんにコメント欄にてsingleton.vimをそっと差し出されたので追記。

序文

Vimテキストエディタです。
ですから基本的には自己主張せず、他のエディタのようにテキストを表示したり編集したり出来てほしいですよね。
例えば、GUIエクスプローラにあるファイルを開く時、いちいちVimから:editしたり、Vimのウインドウにドラッグアンドドロップして開くという事はしたくないでしょう。
他のテキストエディタのようにダブルクリックすればすぐ中身を表示してほしいはずです。


しかし、.vimrcに設定を沢山入れていると段々とVimの起動は遅くなります。
人間は無意識と慣れの動物です。
段々とダブルクリックで開くのを避け、Vimで開く場合だけいちいちVimから:editしたり、Vimウインドウにドラッグアンドドロップして開くようになり、そうした無意識下のストレスは段々とあなたをVimから遠ざけていくでしょう。
もしくは、.txtなどの拡張子Vimを関連付けていないあなたは、それが嫌で関連付けをやめたのではないでしょうか?
最初からVim内で全て完結すれば問題ない?
果たしてそれが可能でしょうか。
Webブラウザからダウンロードしたファイルはどうやって閲覧しますか?
冒頭で言ったように:editする?もしくはunite.vimのようなプラグインで素早く開けるから問題ない?
ダウンロードしたファイルが目の前にあるとしたら?
もしそんな状況でもVimが使いやすいと言い張るのなら、はっきり言いましょう、あなたは飼いならされています。
もはやストレスを感じる事にも慣れてしまい、Vimを使うのではなくVimに使われてしまっている状態です。*1

解決

少し煽り過ぎましたかもしれませんが、要はEmacsにおけるemacsclientのような機能があれば良い訳です。
しかしご存知でしょうか?
Vimは既にそれに相当する機能を持っています。
それは+clientserver機能です。


singleton.vimはこの機能を使ってVimを単一インスタンスのみしか起動させないようにします。
neobundle.vimなどでインストールしたのち、以下の設定を.vimrcに書きます。

call singleton#enable()

これであなたはVimの起動速度に不満を感じることもないでしょう。

解決策 その2

以下の設定はid:thincaさんからsingleton.vimをオススメされる前に私が書いた荒削りなVimscriptですが、一応そのままにしておきます。
(id:thincaさんのsingleton.vimVimプラグイン化されているのでインストールも簡単です)

---------------

以下の設定を.vimrcに追加します。

" If starting gvim && arguments were given
" (assuming double-click on file explorer)
if has('gui_running') && argc()
    let s:running_vim_list = filter(
    \   split(serverlist(), '\n'),
    \   'v:val !=? v:servername')
    " If one or more Vim instances are running
    if !empty(s:running_vim_list)
        " Open given files in running Vim and exit.
        silent execute '!start gvim'
        \   '--servername' s:running_vim_list[0]
        \   '--remote-tab-silent' join(argv(), ' ')
        qa!
    endif
    unlet s:running_vim_list
endif

上記の設定を入れた状態でエクスプローラ上でダブルクリックしてみてください。
すでにVimが起動している場合は起動済みのVimでファイルを開くはずです。
これでファイルを開く事が可能になりました。

常駐化

某秀○エディタには常駐機能があるようですが、singleton.vimまたは「解決策 その2」の設定を.vimrcに入れておき、
VimWindows起動時に最小化しながら開いておけば同じことが実現できます。
具体的にはスタートアップフォルダに以下のようなショートカットを置きます。


あなたはVimが他とは一線を画したエディタだったからこそパートナーとして選んだはずです。
しかし段々とVimの他のエディタとは違う使いにくさに辟易してきた部分もあるのではないでしょうか?
だとしたらVimにそれを伝えてあげるべきです。
あなたはVimmerなのですから、共通言語であるVimscriptでVimを調ky、もとい使いやすく変えられる力を持っています。
またそうした設定は、他のVimmerと共有すると「あるある!」と同意が得られるかもしれません。
そうした仲間との触れ合いやVimのある生活はあなたに潤いを与えるでしょう。

上の文章は適当な事しか言ってないので読み飛ばしても構いません。

FAQ Q1. それ.vimrcに書かなくても--remote-tab-silent付けて起動すれば同じことできるよね?

A1. 実はそうです。
というかこの設定も--remote-tab-silentを利用しています。
この設定を書いた理由は、Windowsの仕様に阻まれ満足の行く動作が得られなかったからです。


最初は、この挙動にするために、vim.exeへの引数に「--remote-tab-silent」を追加したショートカットを作って、適当な拡張子(.txtなど)にその関連付けて済まそうとしました。
しかし、なぜかショートカットを指定しても参照先のvimが選択されてしまいます。
調べてみると、Windowsでは、拡張子に関連付けるプログラムはexeかbat以外指定できないという事実を知りました。
仕方がないので拡張子には今まで通りgvim.exeを関連付けて、.vimrcで--remote-tab-silent相当の設定を入れることにしました。


exeかバッチファイルが許されるなら、バッチファイルを作ればよかったのでしょうか?
しかし、以下のデメリットがあります。

また、.vimrcで実装することによって以下のメリットがあります。

  • (vimではなく)gvimで起動し、かつ引数が存在する場合のみ--remote-tab-silentを実行している
  • 引数が存在しなかった場合には.vimrcを読み込まずに起動する*2など、Vimscriptなので挙動を変えるのも自由です。

FAQ Q2. これWindows以外でも使えるの?

A2. 使えます。

FAQ Q3. 最小化で起動するショートカット置いても最小化されないんだけど

A3. 'guioptions'のいくつかのフラグをセットすると、強制的にフォアグラウンドにウインドウが持っていかれてしまうようです。
このようにVimのウインドウにフォーカスが移った際にセットして対処しましょう。

" Must be set in .vimrc
set guioptions+=p

" These flags are set on FocusGained
" because "cmd.exe start /min" doesn't work.
" (always start up as foreground)
augroup vimrc-guioptions
    autocmd!
    autocmd FocusGained * set guioptions=agitrhpF | autocmd! vimrc-guioptions
augroup END

しかしいくつかのフラグはこのように遅延してセットされると意味をなしません。
このようなフラグはFocusGained時ではなく、普通にセットしましょう。
上で言うと「p」フラグはFocusGained時ではなく.vimrc読み込み時にセットされていますね。
その他に遅延してセットされると意味をなさないフラグについて
「help 'guioptions'」から引用すると、今の所以下の3つが当てはまるようです。

'f' (中略)
Note:

このオプションはファイル vimrc 内で設定するよう注意。ファ
イル|gvimrc|が読み込まれたときはフォーキングがすでに実行されて
いるかもしれない。


'M' (中略)
Note

このフラグは、構文認識やファイルタイプ認識を起動する前に、
ファイル .vimrc 内で追加されていなければならない (ファイル
.gvimrc が読み込まれたときには、システムメニューはすでに読み込
まれた後である。コマンド ":syntax on" と ":filetype on" でもメ
ニューは読み込まれる)。


'p' (中略)
...れはGUIを開始する前に設定しなければならない。

ユーザのファイル
|gvimrc|内で設定すること。GUIが開始した後にこのフラグを追加した
り取り除いたりしても、効果はない。

*1:使いやすいのではなく、使い慣れただけです。

*2:私はこの挙動にしています。理由はダブルクリックで開いた時にファイルが開くのをいちいち待たされたくないためで、.vimrcを読み込むと遅い(10秒ほどかかる)からです。