差分

Nvim :help ページは、ソースからtree-sitter-vimdocパーサーを使用して生成されています。


diff-mode このファイルでは、差分機能について説明します。同じファイルの2〜8つのバージョンの違いを表示します。
基本的な内容は、ユーザーマニュアルのセクション08.7で説明されています。

1. 差分モードの開始 start-vimdiff

差分モードで編集を開始するには、"nvim -d"を実行します。これは通常通りNvimを起動し、さらに引数の間の違いを表示するように設定します。
nvim -d file1 file2 [file3 [file4]]
-d引数に加えて、読み取り専用モードには-Rを使用できます。
2番目以降の引数は、ディレクトリ名にすることもできます。Vimは、最初の引数のファイル名をディレクトリ名に追加して、ファイルを見つけます。
デフォルトでは、内部差分ライブラリが使用されます。'diffopt'または'diffexpr'が設定されている場合、外部の "diff" コマンドが使用されます。これは、そのようなdiffプログラムが利用可能な場合にのみ機能します。
差分は、現在のタブページtab-pageに対してローカルです。別のタブページのウィンドウで差分を見ることはできません。これにより、それぞれのタブページで複数の差分を同時に表示できます。
Nvimは、各ファイルに対してウィンドウを開きます。これは、-O引数を使用するようなものです。これは垂直分割を使用しますが、水平分割を希望する場合は、代わりに-o引数を使用してください。
nvim -d -o file1 file2 [file3 [file4]]
常に水平分割を希望する場合は、'diffopt'に "horizontal" を含めます。
編集された各ファイルで、以下のオプションが設定されます。
'diff' オン 'scrollbind' オン 'cursorbind' オン 'scrollopt' は "hor" を含む 'wrap' オフ、または'diffopt'に "followwrap" が含まれる場合はそのまま 'foldmethod' "diff" 'foldcolumn' 'diffopt'の値、デフォルトは2
これらのオプションは、ウィンドウに対してローカルに設定されます。別のファイルを編集すると、グローバル値にリセットされます。ファイルを再編集するとき、モードラインからオプションを上書きすることができます。ただし、'diff'が設定されている場合、'foldmethod''wrap'はモードラインから設定されません。オプションを元に戻す簡単な方法については、:diffoffを参照してください。
表示される差分は、実際にはバッファ内の差分です。そのため、ファイルのロード後に変更を加えると、表示される差分に含まれます。時々 ":diffupdate" を実行する必要があるかもしれません。すべての変更がすぐに反映されるわけではありません。特に外部diffコマンドを使用している場合はそうです。
vimrcファイルでは、Vimが差分モードで起動されたときに特別な処理を行うことができます。次のような構成を使用できます。
if &diff
   setup for diff mode
else
   setup for non-diff mode
endif
すでにVimにいる場合は、3つの方法で差分モードを開始できます。
E98
:diffs[plit] {filename} :diffs :diffsplit ファイル{filename}に新しいウィンドウを開きます。オプションは、現在および新しく開かれたウィンドウに対して "nvim -d" と同様に設定されます。'diffexpr'も参照してください。
:difft :diffthis :difft[his] 現在のウィンドウを差分ウィンドウの一部にします。これは、 "nvim -d" と同様にオプションを設定します。
:diffp[atch] {patchfile} E816 :diffp :diffpatch 現在のバッファを使用し、{patchfile}にある差分でパッチを適用し、結果のバッファを開きます。これは、 "nvim -d" と同様にオプションを設定します。{patchfile} は、 "patch" プログラムが理解できる、または'patchexpr'が処理できる任意の形式にすることができます。{patchfile} には、現在のファイルである1つのファイルの差分のみを含める必要があることに注意してください。{patchfile} に他のファイルの差分も含まれている場合、結果は予測できません。Vimは、現在のディレクトリ内のファイルが誤ってパッチされないように、ディレクトリを /tmp に変更します。しかし、それでもさまざまな ".rej" ファイルが作成される可能性があります。また、絶対パス名が存在する場合、これらのファイルにもパッチが適用される可能性があります。
これらのコマンドで垂直分割を使用するには、:verticalを前に付けます。例:
:vert diffsplit main.c~
:vert diffpatch /tmp/diff
常に垂直分割を希望する場合は、'diffopt'に "vertical" を含めます。
E96
'diff'が設定されたバッファは最大8つまで使用できます。
オプション値はバッファと共に記憶されるため、別のファイルをしばらく編集してから同じファイルに戻ると、再び差分モードになります。
:diffo :diffoff :diffo[ff] 現在のウィンドウの差分モードをオフにします。'diff'が設定されていない場合でも、関連するオプションをリセットします。
:diffo[ff]! 現在のウィンドウと、現在のタブページ内で'diff'が設定されているすべてのウィンドウの差分モードをオフにします。関連オプションのリセットは、'diff'が設定されているウィンドウでのみ行われます。現在のウィンドウに'diff'が設定されていない場合、そのウィンドウのオプションは変更されません。隠しバッファも、差分表示されたバッファのリストから削除されます。
:diffoffコマンドは、関連するオプションを:diffsplit:diffpatch:diffthisを使用するか、Vimを差分モードで起動したときの値にリセットします。:diffoffを2回使用すると、最後に保存された値が復元されます。それ以外の場合は、デフォルト値に設定されます。
'diff' オフ 'scrollbind' オフ 'cursorbind' オフ 'scrollopt' "hor" なし 'wrap' オン、または'diffopt'に "followwrap" が含まれる場合はそのまま 'foldmethod' "manual" 'foldcolumn' 0
'foldenable'は、ほとんどの場合オフにリセットされます。これは、'foldmethod'が "manual" に復元されたときです。折りたたみ自体はクリアされませんが、表示されないはずです。'foldenable'をリセットするのが最良の方法です。

2. 差分の表示 view-diffs

差分ウィンドウには、同じテキストが表示され、違いが強調表示されます。テキストをスクロールすると、'scrollbind'オプションにより、他のウィンドウのテキストもスクロールされます。垂直分割では、テキストは正しく配置されます。
テキストの配置は、以下の場合に正しく行われません。
'wrap'がオンの場合、一部の行は折り返されて2行以上の画面行を占めます。
折りたたみが一方のウィンドウでは開いていて、もう一方のウィンドウでは開いていない場合
'scrollbind'がオフの場合
テキストに変更が加えられた場合
'diffopt'に "filler" がない場合、削除/挿入された行によって配置がずれます。
'diff'オプションが設定されているウィンドウで編集されたすべてのバッファは、差分に含まれます。これは、隠しバッファにも可能です。これを実現するには、最初にウィンドウで編集しておく必要があります。隠しバッファを削除するには、:diffoff!を使用します。
:DiffOrig diff-original-file 'diff'はウィンドウローカルオプションであるため、同じバッファを一方のウィンドウでは差分モードで、もう一方のウィンドウでは「通常」モードで表示できます。また、ファイルがロードされてからバッファに加えた変更を表示することもできます。Vimでは同じファイルに2つのバッファを持つことができないため、別のバッファが必要です。このコマンドは便利です。
command DiffOrig vert new | set buftype=nofile | read ++edit # | 0d_
       \ | diffthis | wincmd p | diffthis
":DiffOrig" を使用して、現在のバッファとロード元のファイルの違いを確認します。
アンロードされたバッファは、差分には使用できません。ただし、隠しバッファでは機能します。":hide" を使用すると、バッファをアンロードせずにウィンドウを閉じることができます。バッファを差分に使用したままにしたくない場合は、非表示にする前に ":set nodiff" を実行してください。
:dif :diff :diffupdate :dif[fupdate][!] 差分の強調表示と折りたたみを更新します。
Vimは、テキストに変更を加えたときに差分を更新しようとします。これは主に、挿入された行と削除された行を処理します。行内の変更や、より複雑な変更は、差分の更新を引き起こしません。差分の更新を強制するには、以下を使用します。
:diffupdate
!が含まれている場合、Vimはファイルが外部で変更され、再ロードする必要があるかどうかを確認します。:checktime が使用された場合のように、変更されたファイルごとにプロンプトが表示されます。
Vimは、一方のウィンドウには存在しないが、もう一方のウィンドウには存在する行のフィラー行を表示します。これらの行は、別のファイルに挿入されたか、このファイルで削除されました。'diffopt'オプションから "filler" を削除すると、Vimはこれらのフィラー行を表示しなくなります。
折りたたみは、変更されていないテキストを非表示にするために使用されます。折りたたみで使用できるすべてのコマンドについては、折りたたみを参照してください。
折りたたみ含まれていない差分の上の行のコンテキストは、'diffopt'オプションで設定できます。たとえば、コンテキストを3行に設定するには、以下のようにします。
:set diffopt=filler,context:3
差分は、以下のグループで強調表示されます。
hl-DiffAdd DiffAdd 追加(挿入)された行。これらの行はこのバッファには存在しますが、別のバッファには存在しません。 hl-DiffChange DiffChange 変更された行。 hl-DiffText DiffText 変更された行内の変更されたテキスト。Vimは、異なる最初の文字と、異なる最後の文字(行の末尾から検索)を見つけます。その間のテキストが強調表示されます。これは、途中の部分が同じままであっても強調表示されることを意味します。'diffopt'フラグ "iwhite" および "icase" がここで使用されます。 hl-DiffDelete DiffDelete 削除された行。フィラー行とも呼ばれます。これらの行はこのバッファには実際には存在しないためです。

3. 差分へのジャンプ jumpto-diffs

差分へのジャンプには、2つのコマンドを使用できます: [c
[c 前の変更の開始位置に後方にジャンプします。回数が使用されている場合は、その回数だけ実行します。 ]c
]c 変更の開始位置まで前方にジャンプします。カウントが指定された場合は、その回数だけジャンプします。
カーソルが移動できる変更がない場合はエラーになります。

4. 差分のコピー copy-diffs E99 E100 E101 E102 E103

マージ
あるバッファから別のバッファにテキストをコピーするためのコマンドが2つあります。その結果、指定された範囲内でバッファが等しくなります。
:diffg :diffget :[range]diffg[et] [bufspec] 現在のバッファを変更して、別のバッファとの差分を元に戻します。[bufspec]が指定されている場合は、そのバッファが使用されます。[bufspec]が現在のバッファを参照している場合は、何も起こりません。それ以外の場合は、diffモードの別のバッファが1つだけ存在する場合にのみ機能します。[range]については以下を参照してください。
:diffpu :diffput E793 :[range]diffpu[t] [bufspec] 別のバッファを変更して、現在のバッファとの差分を元に戻します。":diffget"と同様ですが、現在のバッファではなく、別のバッファが変更されます。[bufspec]が省略され、<'modifiable'>が設定されているdiffモードの別のバッファが複数ある場合、これは失敗します。[range]については以下を参照してください。
do
[count]do 範囲なしの":diffget"と同じです。"o"は"obtain"の略です("dg"は使用できません。"dgg"の始まりになる可能性があります!)。注:これはビジュアルモードでは機能しません。[count]を指定すると、":diffget"の[bufspec]引数として使用されます。
dp
[count]dp 範囲なしの":diffput"と同じです。注:これはビジュアルモードでは機能しません。[count]を指定すると、":diffput"の[bufspec]引数として使用されます。
[range]が指定されていない場合、カーソル位置またはそのすぐ上の差分が影響を受けます。[range]が使用されている場合、Vimは指定された行のみをputまたはgetしようとします。削除された行がある場合、これは常に可能とは限りません。
バッファの最後の行の下に削除された行が存在する場合があります。カーソルがバッファの最後の行にあり、この行の上に差分がない場合、":diffget"コマンドと"do"コマンドは別のバッファから行を取得します。
[range]で別のバッファからこれらの行を取得できるように、最後の行番号に1を加えた値を使用できます。このコマンドは、別のバッファからすべての差分を取得します。
:1,$+1diffget
削除された行は表示されますが、テキスト行としてはカウントされないことに注意してください。カーソルを削除された行に移動することはできません。削除された行を別のバッファの行で埋めるには、その下の行で":diffget"を使用します。E787
変更しようとしているバッファが読み取り専用であり、FileChangedROによってトリガーされる自動コマンドがバッファを変更する場合、コマンドは失敗します。自動コマンドはバッファを変更してはいけません。
上記の[bufspec]引数は、バッファ番号、バッファ名のパターン、またはバッファ名の一部です。例
:diffget diffモードになっている別のバッファを使用します :diffget 3 バッファ3を使用します :diffget v2 "v2"に一致し、diffモードになっているバッファを使用します(例:"file.c.v2")

5. 差分オプション diff-options

'diffopt'および'fillchars'の「diff」項目も参照してください。
diff-slow diff_translations 非常に長い行の場合、差分の構文の強調表示が遅くなる可能性があります。特に、あらゆる種類のローカライズを一致させようとするためです。ローカライズを無効にして構文の強調表示を高速化するには、グローバル変数g:diff_translationsをゼロに設定します
let g:diff_translations = 0
この変数を設定した後、構文スクリプトをリロードします
set syntax=diff

差分の検出 diff-diffexpr

'diffexpr'オプションを設定して、内部diffサポートまたは標準の「diff」プログラムの代わりに、2つのファイルを比較して差分を見つけることができます。
'diffexpr'が空の場合、Vimはこのコマンドを使用してfile1とfile2の差分を検出します
diff file1 file2 > outfile
">"は'shellredir'の値に置き換えられます。
"diff"の出力は、通常の"ed"スタイルのdiffまたはunified diffである必要があります。context diffは機能しません。unified diffの場合、コンテキスト行を使用することはできません。"diff -u"は機能しません。"diff -U0"を使用してください。
この例では、Vimが期待する"ed"スタイルのdiffの形式について説明します
1a2
> bbb
4d4
< 111
7c7
< GGG
---
> ggg
"1a2"項目は、行"bbb"を追加します。"4d4"項目は、行"111"を削除します。"7c7"項目は、行"GGG"を"ggg"に置き換えます。
'diffexpr'が空でない場合、Vimはそれを評価して、上記の形式のdiffファイルを取得します。これらの変数は、使用されるファイル名に設定されます
v:fname_in 元のファイル v:fname_new 同じファイルの新しいバージョン v:fname_out 結果のdiffファイルの書き込み先
さらに、'diffexpr''diffopt'オプションの"icase"と"iwhite"を処理する必要があります。'diffexpr''lines''columns'の値を変更できません。
引数のない関数呼び出しを使用する利点は、高速であることです。expr-option-functionを参照してください。
例(これは'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!コマンドは必要ない場合があります。
'diffexpr'式がs:または<SID>で始まる場合、スクリプトID(local-function)に置き換えられます。例
set diffexpr=s:MyDiffExpr()
set diffexpr=<SID>SomeDiffExpr()
それ以外の場合、式はオプションが設定されたスクリプトのコンテキストで評価されるため、スクリプトローカル項目が使用可能です。
E810 E97 Vimは、diff出力が問題ないかどうかをテストします。問題がない場合は、エラーメッセージが表示されます。考えられる原因
"diff"プログラムを実行できません。
"diff"プログラムは、通常の"ed"スタイルのdiffを生成しません(上記を参照)。
'shell'と関連するオプションが正しく設定されていません。":!sort"のようなコマンドでフィルタリングが機能するかどうか試してください。
'diffexpr'を使用していて、機能しません。問題が明確でない場合は、'verbose'オプションを1以上に設定して、詳細なメッセージを表示してください。
MS-Windows用の自己インストールVimには、diffプログラムが含まれています。持っていない場合は、diff.exeをダウンロードすることをお勧めします。たとえば、https://gnuwin32.sourceforge.net/packages/diffutils.htmから。

パッチの使用 diff-patchexpr

'patchexpr'オプションを設定して、標準の「patch」プログラムの代わりに何か他のものを使用できます。
'patchexpr'が空の場合、Vimは次のように「patch」プログラムを呼び出します
patch -o outfile origfile < patchfile
これは、ほとんどのバージョンの「patch」プログラムで正常に動作するはずです。行の途中にCRがあると問題が発生する可能性があることに注意してください。改行と見なされます。
デフォルトが機能しない場合は、'patchexpr'を同じ効果を持つ式に設定します。これらの変数は、使用されるファイル名に設定されます
v:fname_in 元のファイル v:fname_diff パッチファイル v:fname_out 結果のパッチ適用済みファイル
引数のない関数呼び出しを使用する利点は、高速であることです。expr-option-functionを参照してください。
例(これは'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"で終わるファイルも削除します。
'patchexpr'式がs:または<SID>で始まる場合、スクリプトID(local-function)に置き換えられます。例
set patchexpr=s:MyPatchExpr()
set patchexpr=<SID>SomePatchExpr()
それ以外の場合、式はオプションが設定されたスクリプトのコンテキストで評価されるため、スクリプトローカル項目が使用可能です。
メイン
コマンド索引
クイックリファレンス