Up: 目次   [Index]


バージョン違ひのファイルの編輯 (差分モード)

*diff.txt*      For Vim バージョン 8.1.  Last change: 2019 Nov 10


		  VIMリファレンスマニュアル    by Bram Moolenaar

このファイルでは |+diff| 機能 (同じファイルの 2 つから 8 つまでのバージョン閒の違ひを表示する機能) について解說する。

基本はユーザーマニュアルのセクション |08.7| に記載されてゐる。

1. 差分モードを開始する|start-vimdiff|
2. 差分を眺める|view-diffs|
3. 差分へ移動する|jumpto-diffs|
4. 差分を寫す|copy-diffs|
5. 差分モードのオプション|diff-options|

1. 差分モードを開始する

差分モードで編輯を開始するいちばん簡單な方法は "vimdiff" コマンドである。これは Vim を通常どほり起動して、加へて引數で與へたファイル閒の違ひを表示する。

vimdiff file1 file2 [file3 [file4]]

これは以下に等しい:

vim -d file1 file2 [file3 [file4]]

"gvimdiff" もしくは "vim -d -g" を使ふこともできる。その際は GUI がスタートする。"viewdiff" もしくは "gviewdiff" を使ふこともできる。その際は讀込專用モードでスタートする。"r" が先頭に付け加はれば制限モードになる (|-Z| 參照)。

2 つ目以降の引數にはディレクトリ名を指定することもできる。その際には第 1 引數のファイル名がそのディレクトリ名に追加され、ファイルを檢索するのに利用される。

デフォルトでは 內藏する diff ライブラリが使用される。’diffopt’ もしくは ’diffexpr’ が設定されてゐると、外部の "diff" コマンドが使用される。もちろん該當する diff プログラムが無いと動かないけど。

diff はカレントタブページ |tab-page| にローカルである。他のタブページにあるウィンドウとの差分を見ることはできない。これによつて、複數の差分を同時に見ることが可能になつてゐる。それぞれを別々のタブで開けばよい。

Vim が各ファイルについてウィンドウを開く時に起こることは、|-O| 引數を使つた時に起こることに似てゐる。これには垂直分割が使用される。水平分割を行ひたいならば |-o| 引數を追加する:

vimdiff -o file1 file2 [file3 [file4]]

常に水平分割にしたければ ’diffopt’ に "horizontal" を含めること。

編輯される各ファイルには以下のオプションが設定される:

’diff’on
’scrollbind’on
’cursorbind’on
’scrollopt’"hor" を入れる
’wrap’off
’foldmethod’"diff"
’foldcolumn’2

これらのオプションはウィンドウローカルに設定される。別のファイルを開いた時には、これらはグローバルの値へリセットされる。このオプションはさらにそのファイルを再讀み込みするときモードラインから上書きされることがある。しかし ’diff’ がオンのとき、’foldmethod’ と ’wrap’ はモードラインからはセットされない。 簡單にオプションを元に戾すには ‘:diffoff‘ を參照。

表示される差分はバッファ內の違ひである。だからファイルを讀み込んだ後に變更を行へば、その變更分は差分として表示される。特に外部 diff コマンドを使用してゐる際、全ての變更が卽表示に反映されるわけではないので、時々 ":diffupdate" を行ふと良いだらう。

差分モードで起動した時の特別な設定を .vimrc ファイルに記すことができる。このやうにすれば良い:

if &diff
   setup for diff mode
else
   setup for non-diff mode
endif

既に Vim を利用してゐる時には、3 つの方法で差分モードへ移行することができる。

:diffs[plit] {filename}

ファイル {filename} の新しいウィンドウを開く。現在と新しく開くウィンドウについて "vimdiff" と同樣のオプションをセットする。’diffexpr’ も參照。

:difft[his]

現在のウィンドウを差分ウィンドウの 1 つにする。これにより "vimdiff" と同じオプションが設定される。

:diffp[atch] {patchfile}

{patchfile} 內の差分情報を現在のバッファへ適用し、結果を新しく作成したバッファへ出力する。オプションは "vimdiff" と同樣に設定される。

{patchexpr} の形式は "patch" プログラムか ’patchexpr’ が取り扱へる形式ならどのやうなものでもかまはない。

Note:
{patchfile} は現在のファイルに對して適用可能な差分情報だけを含んでなければならないことに注意。もしも {patchfile} が他のファイル用の差分情報を含んでゐた場合は、結果は豫想不可能となる。Vim は現在のディレクトリのファイルが偶發的に書き換へられてしまふのを避けるためディレクトリを /tmp へ變更する。しかし樣々な ".rej" ファイルが作成されてしまふ問題は依然としてある。また差分情報內にファイルが絕對パスとして與へられた場合には、やはり適用されてしまふ。

このコマンドを垂直分割で使ふには、|:vertical| を先行させる。例:

:vert diffsplit main.c~
:vert diffpatch /tmp/diff

常に垂直分割にしたければ ’diffopt’ に "vertical" を含めること。

diff’ オプションは最大で8つのバッファにまで同時に設定できる。

オプションの値はバッファへ記憶されるので、しばらくの閒異なるファイルを編輯し、また同じファイルへ戾つて再び差分モードを繼續することができる。

:diffo[ff]

カレントウィンドウの差分モードを終了する。’diff’ が設定されてゐてもゐなくても、關聯オプションはリセットされる。

:diffo[ff]!

カレントウィンドウとカレントタブページのすべてのウィンドウの差分モードを終了する。’diff’ が設定されてゐるウィンドウのみ、關聯オプションがリセットされる。カレントウィンドウの ’diff’ オプションが設定されてゐない場合は、そのウィンドウの關聯オプションは變更されない。隱れバッファも、diff 對象のバッファの一覽から削除される。

コマンド ‘:diffoff‘ は關聯するオプションを差分モード實行前の設定値に戾す。それは ‘:diffsplit‘, ‘:diffpatch‘, ‘:diffthis‘ を實行したときの設定値、または Vim を差分モードで起動したときの設定値である。‘:diffoff‘ を 2 回實行したときは最後に保存された値が復元される。

それ以外の場合はデフォルト値に戾す:

’diff’off
’scrollbind’off
’cursorbind’off
’scrollopt’"hor" を外す
’wrap’on
’foldmethod’"manual"
’foldcolumn’0

2. 差分を眺める

差分ウィンドウには同じテキストが、異なるハイライト方法で表示される。テキストをスクロールした際には ’scrollbind’ オプションにより、他のウィンドウも同じやうにスクロールする。垂直分割をしてゐる場合にはテキストは正しく同期する。

テキストの位置は次のやうな場合に狂つていく:

diff’ オプションが設定されてゐるウィンドウで編輯されてゐる全てのバッファが差分へ連結される。これは隱し (hidden) バッファにもあてはまる。これを可能にするには初めに 1 つのウィンドウでそれらが編輯される必要がある。隱れバッファを取り除くには、‘:diffoff!‘ を用ゐること。

diff’ はウィンドウローカルのオプションであるから、1 つのバッファをあるウィンドウでは差分モードで、別のウィンドウでは通常のウィンドウで表示することも可能である。ファイルを讀み込んで以來バッファに對して行つた變更を表示することも可能である。だが、Vim は 1 つのファイルに對して複數のバッファを持つことはできないから、別のバッファを作る必要がある。

次のコマンドが便利である:

command DiffOrig vert new | set bt=nofile | r ++edit # | 0d_
       \ | diffthis | wincmd p | diffthis

(これは |defaults.vim| に書かれてゐる)。":DiffOrig" を實行すると、カレントバッファと元のファイルの差分を見ることができる。

アンロードされたバッファの差分をとることはできない。隱れバッファの差分をとることはできる。コマンド ":hide" を使ふと、バッファをアンロードせずにウィンドウを閉ぢることができる。そのときバッファを差分對象から外したいならば、隱れバッファにする前に ":set nodiff" をする。

:dif[fupdate][!]

差分の强調と折り疊みを更新する。

テキストを變更した時には、Vim は差分情報を最新に保たうと試みる。これの大部分は插入と削除をされた行 (複數も可) に着目して行はれる。1 行內で行はれた變更、及びそれよりも複雜な變更に對しては差分情報は更新されない。差分情報を强制的に更新するには次のコマンドを使ふ:

:diffupdate

! が含まれてゐる場合、Vimは ファイルが外部で變更され、再讀み込みが必要かどうかをチェックする。その際、‘:checktime‘ を使つたときと同樣に、變更されたそれぞれのファイルについてプロンプトが表示される。

Vim は片方のウィンドウには存在しないがもう一方には存在する行については補充して表示する。これらはもう一方のファイルで追加されたかこのファイルで削除された行である。’diffopt’ オプションから "filler" を削除すると Vim はこのやうな行の補充は行はない。

變更されてゐないテキストについては折疊を使用して隱される。折疊に使用できる全てのコマンドについては |folding| を參照。

差分の近邊の折疊に含まれない領域はコンテキストと呼び、その行數を ’diffopt’ オプションで設定できる。以下の例ではこのコンテキストを 3 行に設定してゐる:

:set diffopt=filler,context:3

差分は以下の强調グループで强調表示される:

|hl-DiffAdd| DiffAdd追加(插入)された行。このバッファに存在する行は、別のバッファには存在しない。
|hl-DiffChange| DiffChange變更された行。
|hl-DiffText| DiffText變更された行の中の變更されたテキスト。Vim は異なる最初の文字と、最後の文字を發見する (檢索は行末から行はれる)。その文字の閒のテキストが强調される。これはその閒にあるテキストが例へ同じだつたとしても强調されることを意味する。ここでは ’diffopt’ フラグの "iwhite" と "icase" が適用される。
|hl-DiffDelete| DiffDelete削除された行。補充された行についても、實際そのバッファには存在してゐないことから、このグループが適用される。

3. 差分へ移動する

差分へ移動するのに 2 つのコマンドを使へる:

[c前(上方)の變更の先頭へ移動する。カウントが與へられた場合、その回數繰り返される。
]c次(下方)の變更の先頭へ移動する。カウントが與へられた場合、その回數繰り返される。

カーソルの動く方向に變更がなかつた場合にはエラーになる。

4. 差分を寫す

あるバッファから別のバッファへテキストを複寫する 2 つのコマンドがある。結果的にある範圍について 2 つのバッファの內容は等しくなる。

:[range]diffg[et] [bufspec]

現在のバッファをもう1つのバッファと同じくなるやうに變更をする。[bufspec] が與へられた時は、そのバッファが使用される。[bufspec] がカレントバッファである場合は何も起こらない。さうでなければ差分モードのバッファが他に 1 つしかない時にだけ動作する。[range] については以下を參照。

:[range]diffpu[t] [bufspec]

もう 1 つのバッファを現在のバッファと同じくなるやうに變更する。":diffget" と同樣だが現在のバッファではなく、もう一方のバッファが變更を受ける。[bufspec] が省略され、かつ ’modifiable’ がオンで差分モードにあるバッファが 2 個以上あると、このコマンドは失敗する。[range] については以下を參照。

[count]do

範圍のない ":diffget" と同じ。"o" は "obtain" の意味 ("dgg" と區別できないので、"dg" は使へない)。

Note:
これはビジュアルモードでは機能しない。

[count] を與へた場合、それは ":diffget" に對して [bufspec] 引數として用ゐられる。

[count]dp

範圍のない ":diffput" と同じ。

Note:
これはビジュアルモードでは機能しない。

[count] を與へた場合、それは ":diffput" に對して [bufspec] 引數として用ゐられる。

[range] が與へられない場合にはカーソルの位置かその上の差分が適用される。[range] が使はれた時にはその範圍だけを適用 (put/get) しようと試みる。削除された場合には必ずしも可能なわけではない。

バッファの最後の行のさらに下方に削除された行があることも考へられる。そのときカーソルが最終行にあり、最終行より上に差異がないとき、":diffget" と "do" コマンドはそれらの行を取得する。

超えた位置の行をもう一方のバッファから取得するには、最終行 +1 の行番號を指定する。次のコマンドはもう一方のバッファから完全な差分情報を受け取る:

:1,$+1diffget

Note:
削除された行は畫面に表示こそされてゐるが、テキストラインとしては數へられてゐないことに注意。消された範圍にカーソルを移動することはできない。もう一方のバッファから、削除された行を ":diffget" で取得するには對象行の下方で行ふ必要がある。

變更を受けるバッファが讀み込み專用で、|FileChangedRO| で引き起こされる自動コマンドがバッファを變更するとき、このコマンドは失敗する。この自動コマンドはバッファを變更してはならない。

引數 [bufspec] にはバッファ番號、バッファ名のパターンもしくはバッファ名の一部を使用できる。例:

:diffget差分モードにある別のバッファを使用する
:diffget 33 番のバッファを使用する。
:diffget v2差分モードにある "v2" にマッチするバッファを使用する (例, "file.c.v2")

5. 差分モードオプション

|'diffopt'| と |'fillchars'| の "diff" 項目も參照。

行がとても長いと diff 構文ハイライトが遲くなるかもしれない。その場合は特にたくさんの異なつたローカライゼーションをマッチしようと試みるからである。ローカライゼーションを無效化して構文ハイライトを高速化するには、グローバル變數 g:diff_translations を 0 に設定する:

let g:diff_translations = 0

この變數を設定した後、構文スクリプトを再讀み込みする:

set syntax=diff

差分を發見する

diffexpr’ オプションは、2 つのファイルを比較し差分を取得する標準的な "diff" プログラム以外の何かを利用する場合に設定する。

diffexpr’ が空ならば、Vim は file1 と file2 閒の差分を得るために次のコマンドを使用する:

diff file1 file2 > outfile

">" は ’shellredir’ の値に置き換へられる。

"diff" の出力は通常の "ed" もしくは "unified" 形式の差分でなければならない。コンテキスト差分を使用してはいけない。この例は "ed" 形式用の Vim が求めるフォーマットを示してゐる:

1a2
> bbb
4d4
< 111
7c7
< GGG
---
> ggg

diffexpr’ が空でなければ、差分ファイルを述べた形式で取得するためにそれを評價實行する。これらの變數がファイル名として設定される:

v:fname_in基準となるファイル
v:fname_new同ファイルの新バージョン
v:fname_out結果を出力する差分ファイル

その上、’diffexpr’ は ’diffopt’ オプションの "icase" と "iwhite" についても考慮するべきだらう。’diffexpr’ は ’lines’ と ’columns’ の値を變更できない。

例 (これは ’diffexpr’ が空の時とほぼ同じやうに働く):

set diffexpr=MyDiff()
function MyDiff()
   let opt = ""
   if &diffopt =~ "icase"
     let opt = opt . "-i "
   endif
   if &diffopt =~ "iwhite"
     let opt = opt . "-b "
   endif
   silent execute "!diff -a --binary " . opt . v:fname_in . " " . v:fname_new .
        \  " > " . v:fname_out
   redraw!
endfunction

引數の "-a" は强制的にテキストファイルとして比較するために使はれる。バイナリでの比較は使ひにくい。引數の "–binary" はファイルをバイナリモードで讀み込むために使はれる。DOS で CTRL-Z をテキストの終はりとしないためである。

‘redraw!‘ コマンドは必要ないかもしれない。畫面に何かを表示するシェルコマンドを實行してゐるかどうかに依存する。

Vim は差分の出力結果が妥當であるか檢證する。妥當でない場合、エラーメッセージを得るだらう。起こりうるエラーは:

エラーメッセージがよくわからないときは ’verbose’ オプションを設定してより多くのメッセージを見ることができる。

MS-Windows 用の Vim インストーラには diff プログラムが含まれてゐる。もし diff プログラムを持つてゐない場合はどこかから diff.exe をダウンロードすること。例へば次の場所から入手できる。

http://gnuwin32.sourceforge.net/packages/diffutils.htm

パッチを使用する

patchexpr’ オプションは、標準的な "patch" プログラム以外の何かを利用する場合に設定する。

patchexpr’ が空ならば、Vim は "patch" を次のやうに呼び出す:

patch -o outfile origfile < patchfile

これはほとんどのバージョンの "patch" で正しく働くだらう。行中閒の CR が、改行記號として解釋され問題を起こすことはあるかもしれない。

デフォルトが正しく働かないのならば、同樣の働きをする式を ’patchexpr’ に設定する。これらの變數がファイル名として設定される。

v:fname_in基準となるファイル
v:fname_diffパッチファイル
v:fname_outパッチ適用結果を出力するファイル

例 (これは ’patchexpr’ を空にしたのと同じ働きをする):

set patchexpr=MyPatch()
function MyPatch()
   :call system("patch -o " . v:fname_out . " " . v:fname_in .
   \  " < " . v:fname_diff)
endfunction

利用する "patch" プログラムが望んでゐない副作用をしてゐないことを確認する必要がある。例へば消されるべき付加的なファイルが生成されてゐないか用心する必要がある。ファイルにパッチをあてる以上のことは何もすべきではない。

Vim は ’patchexpr’ を實行する前に "/tmp" か他の一時ディレクトリへ現在のディレクトリを移動する。これにはカレントディレクトリの別のファイルへ偶然にパッチがあたつてしまふのを避ける狙ひがある。Vim は v:fname_in で始まり ".rej" や ".orig" で終はる名前のファイルを消すこともする。


Up: 目次   [Index]