momonga.vim #5 でコミットバッファ編集プラグイン committia.vim を完成させた

f:id:rhysd:20140726130221j:plain

先週の土曜日に武蔵野プレイスで開催された Vim 関連のもくもく会イベント,momonga.vim #5 に参加してきました. 明日が momonga.vim #6 なのでギリギリ間に合ったと思います.

コミットバッファ用プラグイン committia.vim つくった

今回は,以前 TokyoVim でプロトタイプを作成していた committia.vim (自主制作漫画誌展示即売会とは関係ないです)をとりあえず使えるところまで持っていきました.

rhysd/committia.vim - Github

committia.vim はコミットバッファを編集するためのプラグインです.普段 git commit などするとコミットのためのバッファが出ると思いますが,committia.vim をインストールしているとそのバッファが複数ウィンドウのリッチなものになります.

screen shot

横幅が十分にあるウィンドウで git commit を実行すると,上記のような2カラム,3ウィンドウのコミットウィンドウが表示されます.右がコミットの diff を表示するウィンドウ,左上がメッセージ編集ウィンドウ,左下がステータスウィンドウです. 分割して画面右半分に diff を表示することによって画面を有効に使います.

また,committia.vim は各ウィンドウが開いたときのフックを用意しており,次のように書くとエディットウィンドウの中でのみ設定したいマップや設定を書くことができ,下記のように .vimrc に書いておくとエディットウィンドウが開いた時に edit_open() 辞書関数が呼ばれます.

let g:committia_hooks = {}
function! g:committia_hooks.edit_open(info)
    " Additional settings
    setlocal spell

    " If no commit message, start with insert mode
    if a:info.vcs ==# 'git' && getline(1) ==# ''
        startinsert
    end

    " Scroll the diff window from insert mode
    " Map <C-n> and <C-p>
    imap <buffer><C-n> <Plug>(committia-scroll-diff-down-half)
    imap <buffer><C-p> <Plug>(committia-scroll-diff-up-half)

endfunction

この設定では,コミットメッセージが未記入の場合はコミットメッセージを書き込むためにインサートモードから開始するようになっています. また,インサートモードの <C-n><C-p> に diff ウィンドウのスクロール用マッピングを割り当てています.これはエディットメッセージをインサートモードで書いている時に,インサートモードから抜けること無く diff ウィンドウを上下させてコミットの中身をみるためのものです.今まではコミットバッファを開いてから画面を分割し,片方のウィンドウでメッセージを書きつつもう片方のウィンドウでコミットの diff をスクロールして眺めていたので,それを短縮したかたちになります. ちなみに,このスクロールの実装はかなりハマって,thinca さんに助けてもらったので下の方で問題点とハマリポイントを書きます. さらに,特に設定しなくてもメッセージエディットウィンドウを閉じたときに他のウィンドウも自動で閉じるようになっています.

上記の2カラムのウィンドウはウィンドウ幅が十分大きい場合でした.では,ウィンドウ幅がせまい場合はどうなるのかというと,エディット&ステータスウィンドウと diff ウィンドウの上下2ウィンドウの画面になります.これは uasi さんによるコントリビューションです.

single column mode

とりあえず,普段使いではそれなりに満足していますが,次のような拡張を考えています.

  • テストを書く(必須)
  • ドキュメント(README で十分な気もするので optional)
  • 他の VCS のサポート(optional)

もしよろしければ,お試しください.

マッピングのハマリポイント

上記の <Plug>(committia-scroll-diff-down-half)<Plug>(committia-scroll-diff-up-half) は,最初次のようなマッピングになっていました.

inoremap <silent> <Plug>(committia-scroll-diff-down-half) <C-o>:call committia#scroll_window('diff', "\<C-d>")<CR>
inoremap <silent> <Plug>(committia-scroll-diff-up-half) <C-o>:call committia#scroll_window('diff', "\<C-u>")<CR>

上記のうち,down はうまく動くのに up がうまく動かなくてかなりハマりました. マンボウの言うことには,Vimマッピングlhs だけでなく rhs のほうの "\<C-d>""\<C-u>" の中も対応するキーシーケンスに置き換えてしまいます.なので,up のほうのマッピングは途中で生の Ctrl + u が挿入されてしまい,入力中のコマンドラインが前消しされてしまいます. 普段から <CR> などをマッピングrhs に書いているのでこの挙動は当たり前といえば当たり前なのですが,展開対象が文字列の中だったので注意が及びませんでした…

momonga.vim #5 のようす

午前中の用事に結構時間を取られたので昼ごはんを購入して直接会場に向かい着席.真正面が thinca さんだったので,進捗について圧力をかけていくことになりました.ぼちぼち自己紹介がはじまり,少し遅れて隣に座った方が glowshi-ft.vim をつくった saihoooooooo さんだったので,ぼちぼち気になっていた点とかを聞きながら,基本もくもくしてました. あと,詰まったところは積極的に thinca さんに訊くようにして進捗を図りました.毎度ありがとうございます. そんな感じで今回はどうにかぼちぼちやりたいことがやれた感じでした.

もくもく会の後は恒例の懇親会で aomoriringo さんや saihoooooooo さんと色々話し,ご飯のあとはさらにももんが邸で少し続きをやろうとなりました. ただ,この時点で7人いて,ちょっとももんが邸が手狭だったのでまずは部屋の掃除から始まり,(さすがに7人いるとわりとすぐに終わって)無事Lingr作業をしていました. 23時ぐらいで終電だったので,残る組の thinca さんとももんがさんを残して帰りました.

皆さん,お疲れ様でした.進捗どうですか?