Vimのdiffモード機能はVimを使うべき一つの大きな理由になるくらい便利なものだと思います。
違いを見るためだけでも左右に並べて見れるので diff
コマンドなんかよりもよりわかりやすく見ることが出来ます。
そのdiffモード関連のVimの機能やプラグイン等のまとめ。
2つの似たようなファイルを比べたい時に
$ vim -d a.txt b.txt
とすると2つを比べた状態でファイルを開くことが出来ます。
3つ以上同時に比較することも可能です。
diffモードでは以下のオプションがセットされます。
diff
: onscrollbind
: oncursorbind
: onscrollopt
: includes “hor”wrap
: offfoldmethod
: “didf”foldcolumn
: value from ‘diffopt’, default is 2Vim, :help diff
vim -d
は
$ vimdiff a.txt b.txt
とvimdiff
というコマンドを呼ぶのと同じです。
vimdiff
を確認してみるとただのvim
へのシンボリックリンクになってると 思いますが、 Vimではコマンド自体の名前をみて追加のオプションを渡す様になっています。
実際、
$ cd /tmp && touch a.txt b.txt
$ ln -s /usr/bin/vim ./vimdiff
$ ./vimdiff a.txt b.txt
とかすればdiffモードで立ち上がります。
すでに立ち上げてる時に他のファイルと比較したいときは コマンドラインモードで
:diffsplit b.txt
とdiffsplit
(またはdiffs
)を使って他のファイルを開きます。
[c
: 次のdiff箇所へ移動。]c
: 前のdiff箇所へ移動。:diffget
、:diffg
: diff行で現在のバッファの内容をもう片方のバッファへコピー。do
: “diff obtain”、diff行で現在のバッファの内容をもう片方のバッファへコピー。:diffput
、:diffpu
: diff行で現在のバッファの内容をもう片方のバッファへコピー。dp
: “diff put”、diff行で現在のバッファの内容をもう片方のバッファへコピー。diffoff
: diffモードを終了する。diffupdate
: diff状態をアップデート。:diffget
とdo
、及び:diffput
とdp
は同じ操作ですが、 コマンドモードのdiffget
などは範囲を選んでVisualモードに入ってからも 使うことが出来、離れたdiffも一気にマージすることが可能です。
範囲を選んでからd
を押してしまうとその部分が消えてしまうので do
、dp
はVisualモードでは使えません1。
3つ以上のファイルを同時に開いている時には、
:diffget 3
または
3do
の様にマージするバッファを指定します。
[c
、]c
とdo
、dp
をよく使います。
これらのコマンドでのマージは、diffのある行を含む範囲を選んでいるか、 diffのある行、またはその一つ下の行にいる時に出来ます。
相手にしか無い行はそもそも該当行にカーソルが行けませんが 一つ下の行に行くとdo
とかが使えます。
diffモードでは上に書いたように幾つかの設定が特別に自動でセットされたりしますが diffモードの時だけ設定を変えたい時には &diff
をチェックして行います。
1 2 3 4 5 6 7 8 |
|
こんな感じで。スペルチェックなんかは diffモードでもオンにしておくとかなり煩くなってしまうこともあるのでオフにしています。
VimEnter
はVimを開くとき、FilterWritePre
は diff
モードに入るときに該当するのでこれらの時に行うように。
また、diffモードの設定としてdiffopt
というパラメーターがあって、 これに以下の様な値を設定することが出来ます。
filter
: 片方だけに存在する行がある場合、無いファイルの方の行を空ける様になる。context:{n}
: 変更がある行間にn行表示する。それ以上ある場合にはfoldされる。設定が無いと6行。icase
: 大文字小文字を区別しない。iwhite
: スペースの違いは無視。horizontal
: 縦分割でdiffモード。vertical
: 縦分割でdiffモード。foldcolumn:{n}
: diffモード時のfoldcolumn(foldの状況を左側に表示、その幅)の設定。現在の設定は以下のとおり。
1
|
|
また、diffモードで開いて片方を残してそのまま編集したい時、 diffモードが続いてしまって見難いのでdiffoff
をする必要がありますが、 これを自動で行う様に以下の様な設定をしておくと便利です。
1
|
|
diffの表示に使われるカラー設定は以下の4つで、
好みですが使ってるカラースキーマ(ron
)のものが余り気に入らなかったので 以下の様に設定しています。
1 2 3 4 |
|
Vimデフォルトコマンドではありませんが、 Helpに載ってるコマンドで、
1 2 3 4 |
|
の様なDiffOrig
というコマンドを作っておくと、
:DiffOrig
とすることで開いたファイルの初期状態からの違いをdiffモードで見ることが出来るようになります。
.vimrcに必須なものの一つ。
linediff.vimは 任意の二箇所のdiffを表示してくれるプラグイン。
同一ファイル内の2箇所でも可能です。
まず、diffを見たい箇所の一つをVisualモードで選択し、
:LineDiff
コマンドを打ちます。するとその範囲の上と下側にマークがつくので、 その状態でもう一箇所へ移動してVisualモードに入って選択し、 再び
:LineDiff
すると先ほど選択した部分とのdiffが別枠で表示されます。
同じファイル内の同じ様な場所のdiffを見たり、 違うファイルでも一部だけ比較したい時などに便利です。
これを知るまでは見たい部分だけ他のファイルに書きだして vim -d
したりしてましたがこのプラグインで大分作業が楽になりました。
vcscommand.vim はsvnやgit等のバージョン管理システム上のファイルを扱う際に 色々と便利にしてくれるプラグインです。
ファイルのコミットなども出来ますが、 この中にコマンド:VCSVimDiff
または<Leader>cv
で 現在開いているファイルの未コミット分の差分を見ることが出来ます。
基本ターミナルで作業するのでgitコマンドなどをこのプラグインで使うことはありませんが、 このdiff機能はとても便利でよく使います。 無いと困るくらい。
vcscommand.vimの他の機能については以下の記事が詳しいです。
diffchar.vim はdiffの表示時に単語単位のハイライトを強化してくれるプラグイン。
通常、diffモードでは行内に違う部分がある場合、 違う部分が初めて出たところから最後に出るところまで全体がDiffText
のハイライト対象になります。
aaa bbb ccc ddd eee fff ggg hhh
と
aaa bbb xxx ddd eee xxx ggg hhh
を比較した場合、ここではccc
とfff
の部分が違いますが、 ccc ddd eee fff
の部分がハイライトされます。
これがdiffchar.vimを入れるとccc
とfff
の部分だけがハイライトされる様になります。
ただ、場合によっては逆に見づらくなることもあるので 使ってみて、という感じです。
最初入れてちょっとあれかな、と思って外してましたが 今はまた入れています。
vim-diff-enhanced はdiffを作るアルゴリズムを変更できるプラグイン。
diffモードで、
:PatienceDiff
とすると、Patienceアルゴリズムと言うVimで使っているアルゴリズムとは 違うアルゴリズムでdiffを再描写します。
:EnhancedDiffDisable
で元に。
GitHubのREADMEにある例だと、 同じような内容の関数がいくつか続くような時、 本来比べてほしくない部分を比較してしまう時がありますが、 Patienceを使うと綺麗に分けてくれています。
これも場合によってはデフォルトの方が良い場合もありますが、 上記のコマンドで簡単に元に戻せるので入れておくと便利です。
READMEにあるように、デフォルトをPatienceにするように
1 2 3 |
|
の設定を.vimrcで行っています。
同じような理由で、:diffget
に対してdg
を使えないのは、d
がdelete
のコマンドでもあるので、dgg
(現在いる行から上を全て削除)の一部だったりするため。 ↩