neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

diff.txt (22492B)


      1 *diff.txt*      Nvim
      2 
      3 
      4 	  VIM REFERENCE MANUAL	  by Bram Moolenaar
      5 
      6 
      7 						*diff* *diff-mode*
      8 This file describes the diff feature: Showing differences between two to
      9 eight versions of the same file.
     10 
     11 The basics are explained in section |08.7| of the user manual.
     12 
     13                                      Type |gO| to see the table of contents.
     14 
     15 ==============================================================================
     16 1. Starting diff mode					*start-vimdiff*
     17 
     18 To start editing in diff mode, run "nvim -d".  This starts Nvim as usual, and
     19 additionally sets up for viewing the differences between the arguments. >
     20 
     21 nvim -d file1 file2 [file3 [file4]]
     22 
     23 In addition to the |-d| argument, |-R| may be used for readonly mode.
     24 
     25 The second and following arguments may also be a directory name.  Vim will
     26 then append the file name of the first argument to the directory name to find
     27 the file.
     28 
     29 By default an internal diff library will be used.  When 'diffopt' or
     30 'diffexpr' has been set an external "diff" command will be used.  This only
     31 works when such a diff program is available.
     32 
     33 Diffs are local to the current tab page |tab-page|.  You can't see diffs with
     34 a window in another tab page.  This does make it possible to have several
     35 diffs at the same time, each in their own tab page.
     36 
     37 What happens is that Nvim opens a window for each of the files.  This is like
     38 using the |-O| argument.  This uses vertical splits, but if you prefer
     39 horizontal splits use the |-o| argument instead: >
     40 
     41 nvim -d -o file1 file2 [file3 [file4]]
     42 
     43 If you always prefer horizontal splits include "horizontal" in 'diffopt'.
     44 
     45 In each of the edited files these options are set:
     46 
     47 'diff'		on
     48 'scrollbind'	on
     49 'cursorbind'	on
     50 'scrollopt'	includes "hor"
     51 'wrap'		off, or leave as-is if 'diffopt' includes "followwrap"
     52 'foldmethod'	"diff"
     53 'foldcolumn'	value from 'diffopt', default is 2
     54 
     55 These options are set local to the window.  When editing another file they are
     56 reset to the global value.
     57 The options can still be overruled from a modeline when re-editing the file.
     58 However, 'foldmethod' and 'wrap' won't be set from a modeline when 'diff' is
     59 set.
     60 See `:diffoff` for an easy way to revert the options.
     61 
     62 The differences shown are actually the differences in the buffer.  Thus if you
     63 make changes after loading a file, these will be included in the displayed
     64 diffs.  You might have to do ":diffupdate" now and then, not all changes are
     65 immediately taken into account, especially when using an external diff
     66 command.
     67 
     68 In your vimrc file you could do something special when Vim was started in
     69 diff mode.  You could use a construct like this: >
     70 
     71 if &diff
     72    setup for diff mode
     73 else
     74    setup for non-diff mode
     75 endif
     76 
     77 While already in Vim you can start diff mode in three ways.
     78 
     79 						*E98*
     80 :diffs[plit] {filename}					*:diffs* *:diffsplit*
     81 	Open a new window on the file {filename}.  The options are set
     82 	as for "nvim -d" for the current and the newly opened window.
     83 	Also see 'diffexpr'.
     84 
     85 						*:difft* *:diffthis*
     86 :difft[his]	Make the current window part of the diff windows.  This sets
     87 	the options as for "nvim -d".
     88 
     89 :diffp[atch] {patchfile}			 *E816* *:diffp* *:diffpatch*
     90 	Use the current buffer, patch it with the diff found in
     91 	{patchfile} and open a buffer on the result.  This sets the
     92 	options as for "nvim -d".
     93 	{patchfile} can be in any format that the "patch" program
     94 	understands or 'patchexpr' can handle.
     95 	Note that {patchfile} should only contain a diff for one file,
     96 	the current file.  If {patchfile} contains diffs for other
     97 	files as well, the results are unpredictable.  Vim changes
     98 	directory to /tmp to avoid files in the current directory
     99 	accidentally being patched.  But it may still result in
    100 	various ".rej" files to be created.  And when absolute path
    101 	names are present these files may get patched anyway.
    102 
    103 To make these commands use a vertical split, prepend |:vertical|.  Examples: >
    104 
    105 :vert diffsplit main.c~
    106 :vert diffpatch /tmp/diff
    107 
    108 If you always prefer a vertical split include "vertical" in 'diffopt'.
    109 
    110 						*E96*
    111 There can be up to eight buffers with 'diff' set.
    112 
    113 Since the option values are remembered with the buffer, you can edit another
    114 file for a moment and come back to the same file and be in diff mode again.
    115 
    116 						*:diffo* *:diffoff*
    117 :diffo[ff]	Switch off diff mode for the current window.  Resets related
    118 	options also when 'diff' was not set.
    119 
    120 :diffo[ff]!	Switch off diff mode for the current window and in all windows
    121 	in the current tab page where 'diff' is set.  Resetting
    122 	related options only happens in a window that has 'diff' set,
    123 	if the current window does not have 'diff' set then no options
    124 	in it are changed.
    125 	Hidden buffers are also removed from the list of diff'ed
    126 	buffers.
    127 
    128 The `:diffoff` command resets the relevant options to the values they had when
    129 using `:diffsplit`, `:diffpatch`, `:diffthis`, or starting Vim in diff mode.
    130 When using `:diffoff` twice the last saved values are restored.
    131 Otherwise they are set to their default value:
    132 
    133 'diff'		off
    134 'scrollbind'	off
    135 'cursorbind'	off
    136 'scrollopt'	without "hor"
    137 'wrap'		on, or leave as-is if 'diffopt' includes "followwrap"
    138 'foldmethod'	"manual"
    139 'foldcolumn'	0
    140 
    141 'foldenable' will most-likely be reset to off.  That is when 'foldmethod' is
    142 restored to "manual".  The folds themselves are not cleared but they should
    143 not show up, resetting 'foldenable' is the best way to do that.
    144 
    145 ==============================================================================
    146 2. Viewing diffs						*view-diffs*
    147 
    148 The effect is that the diff windows show the same text, with the differences
    149 highlighted.  When scrolling the text, the 'scrollbind' option will make the
    150 text in other windows to be scrolled as well.  With vertical splits the text
    151 should be aligned properly.
    152 
    153 The alignment of text will go wrong when:
    154 - 'wrap' is on, some lines will be wrapped and occupy two or more screen
    155  lines
    156 - folds are open in one window but not another
    157 - 'scrollbind' is off
    158 - changes have been made to the text
    159 - "filler" is not present in 'diffopt', deleted/inserted lines makes the
    160  alignment go wrong
    161 
    162 All the buffers edited in a window where the 'diff' option is set will join in
    163 the diff.  This is also possible for hidden buffers.  They must have been
    164 edited in a window first for this to be possible.  To get rid of the hidden
    165 buffers use `:diffoff!`.
    166 
    167 				*:DiffOrig* *diff-original-file*
    168 Since 'diff' is a window-local option, it's possible to view the same buffer
    169 in diff mode in one window and "normal" in another window.  It is also
    170 possible to view the changes you have made to a buffer since the file was
    171 loaded.  Since Vim doesn't allow having two buffers for the same file, you
    172 need another buffer.  This command is useful: >
    173  command DiffOrig vert new | set buftype=nofile | read ++edit # | 0d_
    174 	\ | diffthis | wincmd p | diffthis
    175 Use ":DiffOrig" to see the differences
    176 between the current buffer and the file it was loaded from.
    177 
    178 A buffer that is unloaded cannot be used for the diff.  But it does work for
    179 hidden buffers.  You can use ":hide" to close a window without unloading the
    180 buffer.  If you don't want a buffer to remain used for the diff do ":set
    181 nodiff" before hiding it.
    182 
    183 					*:dif* *:diff* *:diffupdate*
    184 :dif[fupdate][!]		Update the diff highlighting and folds.
    185 
    186 Vim attempts to keep the differences updated when you make changes to the
    187 text.  This mostly takes care of inserted and deleted lines.  Changes within a
    188 line and more complicated changes do not cause the differences to be updated.
    189 To force the differences to be updated use: >
    190 
    191 :diffupdate
    192 
    193 If the ! is included Vim will check if the file was changed externally and
    194 needs to be reloaded.  It will prompt for each changed file, like `:checktime`
    195 was used.
    196 
    197 Vim will show filler lines for lines that are missing in one window but are
    198 present in another.  These lines were inserted in another file or deleted in
    199 this file.  Removing "filler" from the 'diffopt' option will make Vim not
    200 display these filler lines.
    201 
    202 
    203 Folds are used to hide the text that wasn't changed.  See |folding| for all
    204 the commands that can be used with folds.
    205 
    206 The context of lines above a difference that are not included in the fold can
    207 be set with the 'diffopt' option.  For example, to set the context to three
    208 lines: >
    209 
    210 :set diffopt=filler,context:3
    211 
    212 
    213 The diffs are highlighted with these groups:
    214 
    215 |hl-DiffAdd|	DiffAdd		Added (inserted) lines.  These lines exist in
    216 			this buffer but not in another.
    217 |hl-DiffChange|	DiffChange	Changed lines.
    218 |hl-DiffText|	DiffText	Changed text inside a Changed line.  Exact
    219 			behavior depends on the `inline:` setting in
    220 			'diffopt'.
    221 			With `inline:` set to "simple", Vim finds the
    222 			first character that is different, and the
    223 			last character that is different (searching
    224 			from the end of the line).  The text in
    225 			between is highlighted.  This means that parts
    226 			in the middle that are still the same are
    227 			highlighted anyway.  The 'diffopt' flags
    228 			"iwhite" and "icase" are used here.
    229 			With `inline:` set to "char" or "word", Vim
    230 			uses the internal diff library to perform a
    231 			detailed diff between the changed blocks and
    232 			highlight the exact difference between the
    233 			two.  Will respect any 'diffopt' flag that
    234 			affects internal diff.
    235 			Not used when `inline:` is set to "none".
    236 |hl-DiffTextAdd|  DiffTextAdd	Added text inside a Changed line.  Similar to
    237 			DiffText, but used when there is no
    238 			corresponding text in other buffers.  Not used
    239 			when `inline:` is set to "simple" or "none".
    240 |hl-DiffDelete|	DiffDelete	Deleted lines.  Also called filler lines,
    241 			because they don't really exist in this
    242 			buffer.
    243 
    244 ==============================================================================
    245 3. Jumping to diffs					*jumpto-diffs*
    246 
    247 Two commands can be used to jump to diffs:
    248 							*[c*
    249 [c		Jump backwards to the previous start of a change.
    250 		When a count is used, do it that many times.
    251 							*]c*
    252 ]c		Jump forwards to the next start of a change.
    253 		When a count is used, do it that many times.
    254 
    255 It is an error if there is no change for the cursor to move to.
    256 
    257 ==============================================================================
    258 4. Diff copying			*copy-diffs* *E99* *E100* *E101* *E102* *E103*
    259 							*merge*
    260 There are two commands to copy text from one buffer to another.  The result is
    261 that the buffers will be equal within the specified range.
    262 
    263 						*:diffg* *:diffget*
    264 :[range]diffg[et] [bufspec]
    265 	Modify the current buffer to undo difference with another
    266 	buffer.  If [bufspec] is given, that buffer is used.  If
    267 	[bufspec] refers to the current buffer then nothing happens.
    268 	Otherwise this only works if there is one other buffer in diff
    269 	mode.
    270 	See below for [range].
    271 
    272 					*:diffpu* *:diffput* *E793*
    273 :[range]diffpu[t] [bufspec]
    274 	Modify another buffer to undo difference with the current
    275 	buffer.  Just like ":diffget" but the other buffer is modified
    276 	instead of the current one.
    277 	When [bufspec] is omitted and there is more than one other
    278 	buffer in diff mode where 'modifiable' is set this fails.
    279 	See below for [range].
    280 
    281 						*do*
    282 [count]do	Same as ":diffget" without range.  The "o" stands for "obtain"
    283 	("dg" can't be used, it could be the start of "dgg"!).  Note:
    284 	this doesn't work in Visual mode.
    285 	If you give a [count], it is used as the [bufspec] argument
    286 	for ":diffget".
    287 
    288 						*dp*
    289 [count]dp	Same as ":diffput" without range.  Note: this doesn't work in
    290 	Visual mode.
    291 	If you give a [count], it is used as the [bufspec] argument
    292 	for ":diffput".
    293 
    294 
    295 When no [range] is given, the diff at the cursor position or just above it is
    296 affected.  There can be deleted lines below the last line of the buffer.  When
    297 the cursor is on the last line in the buffer and there is no diff above this
    298 line, and no [range] is given, the diff below the cursor position will be used
    299 instead.
    300 
    301 When [range] is used, Vim tries to only put or get the specified lines.  When
    302 there are deleted lines, they will be used if they are between the lines
    303 specified by [range].
    304 
    305 To be able to put or get those lines to/from another buffer in a [range] it's
    306 allowed to use 0 and the last line number plus one.  This command gets all
    307 diffs from the other buffer: >
    308 
    309 :0,$+1diffget
    310 
    311 Note that deleted lines are displayed, but not counted as text lines.  You
    312 can't move the cursor into them.  To fill the deleted lines with the lines
    313 from another buffer use ":diffget" on the line below them.
    314 							*E787*
    315 When the buffer that is about to be modified is read-only and the autocommand
    316 that is triggered by |FileChangedRO| changes buffers the command will fail.
    317 The autocommand must not change buffers.
    318 
    319 The [bufspec] argument above can be a buffer number, a pattern for a buffer
    320 name or a part of a buffer name.  Examples:
    321 
    322 :diffget		Use the other buffer which is in diff mode
    323 :diffget 3		Use buffer 3
    324 :diffget v2		Use the buffer which matches "v2" and is in
    325 			diff mode (e.g., "file.c.v2")
    326 
    327 ==============================================================================
    328 5. Diff anchors						*diff-anchors*
    329 
    330 Diff anchors allow you to control where the diff algorithm aligns and
    331 synchronize text across files.  Each anchor matches each other in each file,
    332 allowing you to control the output of a diff.
    333 
    334 This is useful when a change involves complicated edits.  For example, if a
    335 function was moved to another location and further edited.  By default, the
    336 algorithm aims to create the smallest diff, which results in that entire
    337 function being considered to be deleted and added on the other side, making it
    338 hard to see what the actual edit on it was.  You can use diff anchors to pin
    339 that function so the diff algorithm will align based on it.
    340 
    341 To use it, set anchors using 'diffanchors' which is a comma-separated list of
    342 {address} in each file, and then add "anchor" to 'diffopt'.  Internally, Vim
    343 splits each file up into sections split by the anchors.  It performs the diff
    344 on each pair of sections separately before merging the results back.
    345 
    346 Setting 'diffanchors' will update the diff immediately.  If an anchor is tied
    347 to a mark, and you change what the mark is pointed to, you need to manually
    348 call |:diffupdate| afterwards to get the updated diff results.
    349 
    350 Example:
    351 
    352 Let's say we have the following files, side-by-side.  We are interested in the
    353 change that happened to the function `foo()`, which was both edited and moved.
    354 
    355 File A: >
    356 int foo() {
    357     int n = 1;
    358     return n;
    359 }
    360 
    361 int g = 1;
    362 
    363 int bar(int a) {
    364     a *= 2;
    365     a += 3;
    366     return a;
    367 }
    368 <File B: >
    369 int bar(int a) {
    370     a *= 2;
    371     a += 3;
    372     return a;
    373 }
    374 
    375 int foo() {
    376     int n = 999;
    377     return n;
    378 }
    379 
    380 int g = 1;
    381 <
    382 A normal diff will usually align the diff result as such: >
    383 
    384 int foo() {     |----------------
    385     int n = 1;  |----------------
    386     return n;   |----------------
    387 }               |----------------
    388                 |----------------
    389 int g = 1;      |----------------
    390                 |----------------
    391 int bar(int a) {|int bar(int a) {
    392     a *= 2;     |    a *= 2;
    393     a += 3;     |    a += 3;
    394     return a;   |    return a;
    395 }               |}
    396 ----------------|
    397 ----------------|int foo() {
    398 ----------------|    int n = 999;
    399 ----------------|    return n;
    400 ----------------|}
    401 ----------------|
    402 ----------------|int g = 1;
    403 <
    404 What we want is to instead ask the diff to align on `foo()`: >
    405 
    406 ----------------|int bar(int a) {
    407 ----------------|    a *= 2;
    408 ----------------|    a += 3;
    409 ----------------|    return a;
    410 ----------------|}
    411 ----------------|
    412 int foo() {     |int foo() {
    413     int n = 1;  |    int n = 999;
    414     return n;   |    return n;
    415 }               |}
    416                 |
    417 int g = 1;      |int g = 1;
    418                 |----------------
    419 int bar(int a) {|----------------
    420     a *= 2;     |----------------
    421     a += 3;     |----------------
    422     return a;   |----------------
    423 }               |----------------
    424 <
    425 
    426 Below are some ways of setting diff anchors to get the above result.  In each
    427 example, 'diffopt' needs to have `anchor` set for this to take effect.
    428 
    429 Marks: Set the |'a| mark on the `int foo()` lines in each file first before
    430 setting the anchors: >
    431 set diffanchors='a
    432 
    433 Pattern: Specify the anchor using a |pattern| (see |:/|).  Here, we make sure
    434 to always start search from line 1 for consistency: >
    435 set diffanchors=1/int\ foo(/
    436 <
    437 Selection: Use visual mode to select the entire `foo()` function body in each
    438 file.  Here, we use two anchors.  This does a better job of making sure only
    439 the function bodies are anchored against each other but not the lines after
    440 it.  Note the `'>+1` below.  The "+1" is necessary as we want the split to
    441 happen below the last line of the function, not above: >
    442 set diffanchors='<,'>+1
    443 <
    444 Manually set two anchors using line numbers via buffer-local options: >
    445 setlocal diffanchors=1,5
    446 wincmd w
    447 setlocal diffanchors=7,11
    448 <
    449 ==============================================================================
    450 6. Diff options						*diff-options*
    451 
    452 Also see 'diffopt' and the "diff" item of 'fillchars'.
    453 
    454 				    *diff-slow* *diff_translations*
    455 For very long lines, the diff syntax highlighting might be slow, especially
    456 since it tries to match all different kind of localisations.  To disable
    457 localisations and speed up the syntax highlighting, set the global variable
    458 g:diff_translations to zero: >
    459 
    460    let g:diff_translations = 0
    461 <
    462 After setting this variable, reload the syntax script: >
    463 
    464    set syntax=diff
    465 <
    466 
    467 
    468 FINDING THE DIFFERENCES					*diff-diffexpr*
    469 
    470 The 'diffexpr' option can be set to use something else than the internal diff
    471 support or the standard "diff" program to compare two files and find the
    472 differences.
    473 
    474 When 'diffexpr' is empty, Vim uses this command to find the differences
    475 between file1 and file2: >
    476 
    477 diff file1 file2 > outfile
    478 
    479 The ">" is replaced with the value of 'shellredir'.
    480 
    481 The output of "diff" must be a normal "ed" style diff or a unified diff.  A
    482 context diff will NOT work.  For a unified diff no context lines can be used.
    483 Using "diff -u" will NOT work, use "diff -U0".
    484 
    485 This example explains the format that Vim expects for the "ed" style diff: >
    486 
    487 1a2
    488 > bbb
    489 4d4
    490 < 111
    491 7c7
    492 < GGG
    493 ---
    494 > ggg
    495 
    496 The "1a2" item appends the line "bbb".
    497 The "4d4" item deletes the line "111".
    498 The "7c7" item replaces the line "GGG" with "ggg".
    499 
    500 When 'diffexpr' is not empty, Vim evaluates it to obtain a diff file in the
    501 format mentioned.  These variables are set to the file names used:
    502 
    503 v:fname_in		original file
    504 v:fname_new		new version of the same file
    505 v:fname_out		where to write the resulting diff file
    506 
    507 Additionally, 'diffexpr' should take care of "icase" and "iwhite" in the
    508 'diffopt' option.  'diffexpr' cannot change the value of 'lines' and
    509 'columns'.
    510 
    511 The advantage of using a function call without arguments is that it is faster,
    512 see |expr-option-function|.
    513 
    514 Example (this does almost the same as 'diffexpr' being empty): >
    515 
    516 set diffexpr=MyDiff()
    517 function MyDiff()
    518    let opt = ""
    519    if &diffopt =~ "icase"
    520      let opt = opt .. "-i "
    521    endif
    522    if &diffopt =~ "iwhite"
    523      let opt = opt .. "-b "
    524    endif
    525    silent execute "!diff -a --binary " .. opt .. v:fname_in .. " " .. v:fname_new ..
    526 	\  " > " .. v:fname_out
    527    redraw!
    528 endfunction
    529 
    530 The "-a" argument is used to force comparing the files as text, comparing as
    531 binaries isn't useful.  The "--binary" argument makes the files read in binary
    532 mode, so that a CTRL-Z doesn't end the text on DOS.
    533 
    534 The `redraw!` command may not be needed, depending on whether executing a
    535 shell command shows something on the display or not.
    536 
    537 If the 'diffexpr' expression starts with s: or |<SID>|, then it is replaced
    538 with the script ID (|local-function|).  Example: >
    539 	set diffexpr=s:MyDiffExpr()
    540 	set diffexpr=<SID>SomeDiffExpr()
    541 Otherwise, the expression is evaluated in the context of the script where the
    542 option was set, thus script-local items are available.
    543 
    544 					*E810* *E97*
    545 Vim will do a test if the diff output looks alright.  If it doesn't, you will
    546 get an error message.  Possible causes:
    547 -  The "diff" program cannot be executed.
    548 -  The "diff" program doesn't produce normal "ed" style diffs (see above).
    549 -  The 'shell' and associated options are not set correctly.  Try if filtering
    550   works with a command like ":!sort".
    551 -  You are using 'diffexpr' and it doesn't work.
    552 If it's not clear what the problem is set the 'verbose' option to one or more
    553 to see more messages.
    554 
    555 The self-installing Vim for MS-Windows includes a diff program.  If you don't
    556 have it you might want to download a diff.exe.  For example from
    557 https://gnuwin32.sourceforge.net/packages/diffutils.htm.
    558 
    559 
    560 USING PATCHES					*diff-patchexpr*
    561 
    562 The 'patchexpr' option can be set to use something else than the standard
    563 "patch" program.
    564 
    565 When 'patchexpr' is empty, Vim will call the "patch" program like this: >
    566 
    567 patch -o outfile origfile < patchfile
    568 
    569 This should work fine with most versions of the "patch" program.  Note that a
    570 CR in the middle of a line may cause problems, it is seen as a line break.
    571 
    572 If the default doesn't work for you, set the 'patchexpr' to an expression that
    573 will have the same effect.  These variables are set to the file names used:
    574 
    575 v:fname_in		original file
    576 v:fname_diff		patch file
    577 v:fname_out		resulting patched file
    578 
    579 The advantage of using a function call without arguments is that it is faster,
    580 see |expr-option-function|.
    581 
    582 Example (this does the same as 'patchexpr' being empty): >
    583 
    584 set patchexpr=MyPatch()
    585 function MyPatch()
    586    :call system("patch -o " .. v:fname_out .. " " .. v:fname_in ..
    587    \  " < " .. v:fname_diff)
    588 endfunction
    589 
    590 Make sure that using the "patch" program doesn't have unwanted side effects.
    591 For example, watch out for additionally generated files, which should be
    592 deleted.  It should just patch the file and nothing else.
    593   Vim will change directory to "/tmp" or another temp directory before
    594 evaluating 'patchexpr'.  This hopefully avoids that files in the current
    595 directory are accidentally patched.  Vim will also delete files starting with
    596 v:fname_in and ending in ".rej" and ".orig".
    597 
    598 If the 'patchexpr' expression starts with s: or |<SID>|, then it is replaced
    599 with the script ID (|local-function|).  Example: >
    600 	set patchexpr=s:MyPatchExpr()
    601 	set patchexpr=<SID>SomePatchExpr()
    602 Otherwise, the expression is evaluated in the context of the script where the
    603 option was set, thus script-local items are available.
    604 
    605 
    606 vim:tw=78:ts=8:noet:ft=help:norl: