webapi-vimとBufWriteCmdでWeb上のリソースをVimで編集する

この記事はVim Advent Calendar 2013の14日目です。
前の記事はVim on Android | 高級粗茶2。でした。


Vimを使っているとWeb上に存在するリソースもVimで扱いたくなることがあります。
そんな時の強力なお供がmattnさん作のwebapi-vimです。
webapi-vimを利用することで簡単にWeb上のリソースをvimに取り込むことができます。

let res = webapi#http#get(s:pull_request_list_url(a:repo), {}, s:github_request_header)

if res.status !~ "^2.*"
  return ['error', 'Failed to fetch pull request list']
endif

let content = webapi#json#decode(res.content)

こんな感じで webapi#http#getやwebapi#http#postを呼び出すことでcurlで通信した結果を取得できます。
JSONを返すAPIであれば、webapi#json#decodeを呼び出すことでvim scriptのディクショナリやリストにデータを変換してくれます。


Web上のリソースを扱う時、保存方法に良く使うテクニックがbuftypeオプションとBufWriteCmdです。

setlocal buftype=acwrite

autocmd BufWriteCmd <buffer> call s:post_comment()

function! s:post_comment()
  let body = join(getline(1, "$"), "\n")
  let b:comment_info.body = body
  if pull_request#post_review_comment(b:repo, b:number, b:comment_info)
    setlocal nomodified
    bd!
  endif
endfunction

buftypeをacwriteに指定する事で、:writeコマンドの実行時に発生するBufWriteCmdイベントでファイルを書き込む処理を行うことができます。
後は任意のvim scriptで書いた関数を呼び出せばオーケーです。
そこでwebapi-vimを使えば、Web上に何かを投稿するような処理をVimで普通に編集して保存するような感覚で利用できます。
autocmdでコマンドを定義する時にはバッファローカルにしておかないと暴発するので注意しましょう。
BufWriteCmdからファイルを書き込む時には、ちゃんとmodified状態を無効にする処理を書いておく必要があります。
普段の:writeコマンドと違って自動では処理してくれません。


最近、このwebapi-vimを利用してPluginを作ったので紹介しておきます。

GitHub - joker1007/unite-pull-request: unite-pull-request is a unite.vim plugin for Viewing GitHub pull request.

uniteでgithubのpull requestの一覧を参照したり、変更されたファイルのdiffをvim上で表示するプラグインです。
githubのWeb UIで見るよりvimで見た方がファイルの差分を確認しやすいのでは?と思って作りました。
また、Vimからレビューコメントを送信することができます。

差分表示画面でEnterを押すと新しくコメント用のバッファが開くので、そこにコメントを書いて普通に保存するように:writeを実行すると、Enterを押したカーソルの行に対してレビューコメントが送信できます。
vim上の表示とgithubのコメント対象行を一致させるのが困難だったので、既に存在するファイルを編集した差分の場合は、下部に表示されているdiffデータのバッファからしかコメントが投稿できないのが難点の一つです。
他にもページネーションを考慮してないのでpull requestの一覧を最新30件しか取得できないとか、まだまだ機能不足な点がありますが興味があったら使ってみてください。

余りvim scriptに詳しくなくても、webapi-vimのおかげで比較的簡単にvimからWeb上のリソースを編集することができるようになります。
webapi-vimで良く利用するWebサービスVimから扱う快感に酔いしれましょう。