koturnの日記

普通の人です.ブログ上のコードはコピペ自由です.

Vimからのvimdiffを便利にしたい

Vimには、vimdiffという機能がある。
これは、Vim上でファイルの差分を確認するものだ。
vimdiffの利点は、

  1. vimでファイルの差分を確認できる
  2. 差分をハイライト表示しており、視覚的で見やすい
  3. 比較ファイルのスクロールが協調して動作する

といったものがある。
これらの点から、ファイルの差分を目で確認したいときにはvimdiffを使うことをオススメする。


vimdiffは、コンソールから
$ vimdiff file1 file2 (file3 file4 ...)
もしくは、
$ vim -d file1 file2 (file3 file4 ...)
とすることで利用可能である。

vimから使用するには、
:diffsplit file
とすればよい。
この場合、カレントバッファで開いているファイルと引数の[file]をvimdiffモードで開く。
しかし、これではdiffoptオプションにverticalが設定されていない場合(デフォルト)、横分割で開かれてしまう。
差分を比較するときには縦分割の方が見やすいので、
:vertical diffsplit file
としよう。


さて、このVimからvimdiffを行うことについて、以下の4点の不満を感じた。

  1. コマンドのタイプ数が多い
  2. 現在のタブページで開かれる
  3. カレントバッファとの比較になる
  4. コンソールからのvimdiffコマンドと違い、複数の引数に対応していない

これらの点を解消するために、自分でコマンドを定義した。
仕様としては、前述の問題点を踏まえたもので、以下のようにした。

  1. コマンド名はDiffとする
  2. 新しいタブページでvimdiffを行う
  3. 可変引数への対応。引数が1つの場合は、カレントバッファとの比較で、引数が2つ以上の場合は、引数に与えたファイル同士の比較とする
function! s:vimdiff_in_newtab(...)
  if a:0 == 1
    tabedit %:p
    exec 'rightbelow vertical diffsplit ' . a:1
  else
    exec 'tabedit ' . a:1
    for l:file in a:000[1 :]
      exec 'rightbelow vertical diffsplit ' . l:file
    endfor
  endif
endfunction
command! -bar -nargs=+ -complete=file Diff  call s:vimdiff_in_newtab(<f-args>)

f:id:koturn:20130810040542g:plain

このDiffコマンドであれば、前述の問題点は解消できる。
コマンド名はDiffと短めにしたが、VimDiffとしてもよいかもしれない。


ところで、最近、以下のkana氏のツイートを見た。

これは、vimdiffを使わずに、単純に2つのファイルを見比べる手法について述べている。
ついでなので、この手法もコマンド化してみた。

function! s:compare(...)
  if a:0 == 1
    tabedit %:p
    exec 'rightbelow vnew ' . a:1
  else
    exec 'tabedit ' . a:1
    setl scrollbind
    for l:file in a:000[1 :]
      exec 'rightbelow vnew ' . l:file
      setl scrollbind
    endfor
  endif
endfunction
command! -bar -nargs=+ -complete=file Compare  call s:compare(<f-args>)

このCompareコマンドも、前述のDiffコマンドと同一の動作をするようにしており、違いはvimdiffモードで閲覧するかどうかである。
また、複数ファイルの比較にも対応しており、
setl scrollbind
としているので、比較しているファイルが協調してスクロールするようになっている。