無数のパッチを組み合わせて君だけの MacVim を作ろう!
この記事は Vim Advent Calendar 2013 の 9 日目の記事です. 昨日は id:daisuzu さんの Fabricで最新のVimをバラまく でした.僕はサーバでの Vim で自前の環境使うのは諦めているので,すごいなぁと感心するばかりです.
先日開催された VimConf2013 にて,パッチ職人である @kaoriya さんや @k_takata さんの発表があり,Vim にはマージされていない多くの便利パッチがあることが分かりました. そこで,この記事ではそれらの公開されているパッチを MacVim に自前で取り込み,ビルド,メンテしていく方法を考えていきたいと思います.
ほしいパッチを探す
まずは適用したいパッチが無ければ話にならないので,公開されているパッチを漁ります. 例えば,以下のリンクが参考になります.
今回は takata さんの breakindent パッチ と kaoriya さんの autoload キャッシュパッチ,Shougo さんの 補完候補を挿入しないようにするパッチ が気になるので導入してみようと思います.
Homebrew の Formula を書く
自分でパッチを当てた MacVim の管理をするために,Mac のパッケージマネージャである Homebrew を使います.
Homebrew では,Formula と呼ばれるビルドスクリプトを Ruby で書くことでパッケージを追加できます.
Formula の書き方は Formula Cookbook などに載っていますが,ここではパッチを追加するだけなので Ruby の知識すらほぼ必要ありません.
Homebrew に元々ある /usr/local/Library/Formula/macvim.rb
をコピーしてきてそれにパッチを追加します.
ファイル名がそのままパッケージ名になるため,まずはファイル名を変更します.俺専用なので,ここでは macvim-rhysd.rb
とします.
さらに,ファイルを開き Formula 名(Formula
クラスを継承しているクラスの名前)を変更します.
これはファイル名と対応していて,ここでは MacVim
を MacVimRhysd
に変更します.
既に Homebrew のデフォルトの MacVim をインストールしている場合,実行ファイル名が被っていてエラーになってしまうので,既に MacVim をインストール済みでないか確認するためのコードを追加します.
conflicts_with 'macvim', :because => 'This formula installs my patched version of MacVim.'
既に MacVim をインストールしている場合は brew unlink
か brew uninstall
します.
最後にパッチを定義します.
適用するパッチを指定するには Formula
クラスの patches
メソッドをオーバーライドします.
def patches { :p1 => [ 'https://bitbucket.org/k_takata/vim-ktakata-mq/raw/98482edd59b30091f30371dcadad4e3ffcc132be/vim-7.4.035-breakindent.patch', 'https://bitbucket.org/koron/vim-kaoriya-patches/raw/6658116d59073a4471a83fea41a0791718773a96/X010-autoload_cache.diff', 'https://gist.github.com/Shougo/5654189/raw' ] } end
patches
メソッドはパッチ一覧の Hash
を返します.キーはパッチを適用する階層(patch
コマンドのオプション)を指定し,その階層で適用するパッチを Array
で指定します.パッチは文字列でそのまま与えても良いですし,パッチが公開されている URL を指定しても良いです.文字列でそのまま与える場合は,DATA
と __END__
を使ってファイル末尾にパッチを書くのが一般的です.
Formula に書くべきはこれだけで,あとは好きなオプションでインストールします.
brew install path/to/macvim-rhysd.vim --HEAD --with-scope --with-luajit --override-system-vim
brew install
はパッチの適用に失敗してもそのまま続行されてしまうので,パッチが正しく当たったかどうかをログで確認しましょう.
これだけでお気に入りのパッチを適用した MacVim が出来上がりました.
パッチ適用済み Vim 用の設定を書く
パッチを適用した Vim を手に入れたら,新しく有効になった機能用の設定を(必要であれば)書きます.
ここで大切なのは,パッチを適用していない Vim であっても問題ないように書くことです.
特定のオプションや変数,関数などを追加するパッチの場合は exists()
を使って判別できます.
if exists('+breakindent') set breakindent endif
さらに,特定の feature を追加するパッチなら has()
で判定できます.最近だと timers
を追加するパッチが熱いようですね.
判別する方法が無い場合は catch
を使って例外を捕まえることでエラーが出るのを回避します.
try set completeopt-=noselect set completeopt+=noinsert let g:neocomplete#enable_auto_select = 1 let g:neocomplete#enable_complete_select = 1 catch /^Vim\%((\a\+)\)\=:E474/ " when the patch isn't applied endtry
この例では,パッチを当てていない Vim ではパッチで追加される noselect
と noinsert
が存在しないため,E474 が発生するのでそれを catch しています.
書いた Formula のメンテナンス
まだ書いた Formula は Homebrew で管理されていません.自分で書いた Formula を Homebrew で管理するには,任意のリポジトリを Homebrew の管理対象に追加する tap
というサブコマンドを追加します.
ここでは macvim-rhysd.rb
を追加した https://github.com/rhysd/homebrew-rhysd というリポジトリを tap します.
brew tap rhysd/homebrew-rhysd
さらに,参考にした本家の MacVim の Formula(macvim.rb
)が更新された場合は自分の手元のものも更新したいです.その場合は macvim.rb
の変更を git diff
で取り,それを手元の macvim-rhysd.rb
に適用します.自動化したい場合は,git の hook を使って brew update
したときに macvim.rb
の変更をチェックするようにすれば良いと思います.
まとめ
これであんなパッチやこんなパッチが適用された俺専用 MacVim が簡単に導入できる環境が整いました. 今回書いた Formula はこちらで公開しています.
なお,俺専用 MacVim は他の誰も使ったことの無い MacVim です.パッチはすべて experimental でそれ自身がバグを含んでいる可能性がある上,他のパッチと競合する可能性もあるので注意が必要です.
今回は Mac 環境についてでしたが,Arch Linux の abs 用の PKGBUILD 版も気が向いたら書きます.
明日は @alpaca_taichou さんです.よろしくお願いします.