vim-patch:9.1.1009: diff feature can be improved

Problem:  diff feature can be improved
Solution: include the linematch diff alignment algorithm
          (Jonathon)

closes: vim/vim#9661

7c7a4e6d1a

Co-authored-by: Jonathon <jonathonwhite@protonmail.com>
This commit is contained in:
zeertzjq
2025-02-03 21:52:53 +08:00
parent 5a7cf85c2c
commit 290bb4c64b
7 changed files with 614 additions and 159 deletions

View File

@@ -184,6 +184,7 @@ information.
mch_memmove memmove mch_memmove memmove
vim_memset copy_chars copy_spaces memset vim_memset copy_chars copy_spaces memset
vim_strbyte strchr vim_strbyte strchr
vim_strnchr strnchr
vim_strncpy strncpy xstrlcpy/xmemcpyz vim_strncpy strncpy xstrlcpy/xmemcpyz
vim_strcat strncat xstrlcat vim_strcat strncat xstrlcat
VIM_ISWHITE ascii_iswhite VIM_ISWHITE ascii_iswhite

View File

@@ -2037,11 +2037,20 @@ A jump table for the options with a short description can be found at |Q_op|.
Option settings for diff mode. It can consist of the following items. Option settings for diff mode. It can consist of the following items.
All are optional. Items must be separated by a comma. All are optional. Items must be separated by a comma.
filler Show filler lines, to keep the text algorithm:{text} Use the specified diff algorithm with the
synchronized with a window that has inserted internal diff engine. Currently supported
lines at the same position. Mostly useful algorithms are:
when windows are side-by-side and 'scrollbind' myers the default algorithm
is set. minimal spend extra time to generate the
smallest possible diff
patience patience diff algorithm
histogram histogram diff algorithm
closeoff When a window is closed where 'diff' is set
and there is only one window remaining in the
same tab page with 'diff' set, execute
`:diffoff` in that window. This undoes a
`:diffsplit` command.
context:{n} Use a context of {n} lines between a change context:{n} Use a context of {n} lines between a change
and a fold that contains unchanged lines. and a fold that contains unchanged lines.
@@ -2052,6 +2061,23 @@ A jump table for the options with a short description can be found at |Q_op|.
value (999999) to disable folding completely. value (999999) to disable folding completely.
See |fold-diff|. See |fold-diff|.
filler Show filler lines, to keep the text
synchronized with a window that has inserted
lines at the same position. Mostly useful
when windows are side-by-side and 'scrollbind'
is set.
foldcolumn:{n} Set the 'foldcolumn' option to {n} when
starting diff mode. Without this 2 is used.
followwrap Follow the 'wrap' option and leave as it is.
horizontal Start diff mode with horizontal splits (unless
explicitly specified otherwise).
hiddenoff Do not use diff mode for a buffer when it
becomes hidden.
iblank Ignore changes where lines are all blank. Adds iblank Ignore changes where lines are all blank. Adds
the "-B" flag to the "diff" command if the "-B" flag to the "diff" command if
'diffexpr' is empty. Check the documentation 'diffexpr' is empty. Check the documentation
@@ -2065,6 +2091,17 @@ A jump table for the options with a short description can be found at |Q_op|.
are considered the same. Adds the "-i" flag are considered the same. Adds the "-i" flag
to the "diff" command if 'diffexpr' is empty. to the "diff" command if 'diffexpr' is empty.
indent-heuristic
Use the indent heuristic for the internal
diff library.
internal Use the internal diff library. This is
ignored when 'diffexpr' is set. *E960*
When running out of memory when writing a
buffer this item will be ignored for diffs
involving that buffer. Set the 'verbose'
option to see when this happens.
iwhite Ignore changes in amount of white space. Adds iwhite Ignore changes in amount of white space. Adds
the "-b" flag to the "diff" command if the "-b" flag to the "diff" command if
'diffexpr' is empty. Check the documentation 'diffexpr' is empty. Check the documentation
@@ -2084,56 +2121,19 @@ A jump table for the options with a short description can be found at |Q_op|.
of the "diff" command for what this does of the "diff" command for what this does
exactly. exactly.
horizontal Start diff mode with horizontal splits (unless linematch:{n} Align and mark changes between the most
explicitly specified otherwise). similar lines between the buffers. When the
total number of lines in the diff hunk exceeds
{n}, the lines will not be aligned because for
very large diff hunks there will be a
noticeable lag. A reasonable setting is
"linematch:60", as this will enable alignment
for a 2 buffer diff hunk of 30 lines each,
or a 3 buffer diff hunk of 20 lines each.
vertical Start diff mode with vertical splits (unless vertical Start diff mode with vertical splits (unless
explicitly specified otherwise). explicitly specified otherwise).
closeoff When a window is closed where 'diff' is set
and there is only one window remaining in the
same tab page with 'diff' set, execute
`:diffoff` in that window. This undoes a
`:diffsplit` command.
hiddenoff Do not use diff mode for a buffer when it
becomes hidden.
foldcolumn:{n} Set the 'foldcolumn' option to {n} when
starting diff mode. Without this 2 is used.
followwrap Follow the 'wrap' option and leave as it is.
internal Use the internal diff library. This is
ignored when 'diffexpr' is set. *E960*
When running out of memory when writing a
buffer this item will be ignored for diffs
involving that buffer. Set the 'verbose'
option to see when this happens.
indent-heuristic
Use the indent heuristic for the internal
diff library.
linematch:{n} Enable a second stage diff on each generated
hunk in order to align lines. When the total
number of lines in a hunk exceeds {n}, the
second stage diff will not be performed as
very large hunks can cause noticeable lag. A
recommended setting is "linematch:60", as this
will enable alignment for a 2 buffer diff with
hunks of up to 30 lines each, or a 3 buffer
diff with hunks of up to 20 lines each.
algorithm:{text} Use the specified diff algorithm with the
internal diff engine. Currently supported
algorithms are:
myers the default algorithm
minimal spend extra time to generate the
smallest possible diff
patience patience diff algorithm
histogram histogram diff algorithm
Examples: >vim Examples: >vim
set diffopt=internal,filler,context:4 set diffopt=internal,filler,context:4
set diffopt= set diffopt=

View File

@@ -351,7 +351,6 @@ Options:
- 'autoread' works in the terminal (if it supports "focus" events) - 'autoread' works in the terminal (if it supports "focus" events)
- 'background' cannot be set to empty. - 'background' cannot be set to empty.
- 'cpoptions' flags: |cpo-_| - 'cpoptions' flags: |cpo-_|
- 'diffopt' "linematch" feature
- 'eadirection' cannot be set to empty. - 'eadirection' cannot be set to empty.
- 'exrc' searches for ".nvim.lua", ".nvimrc", or ".exrc" files. The - 'exrc' searches for ".nvim.lua", ".nvimrc", or ".exrc" files. The
user is prompted whether to trust the file. user is prompted whether to trust the file.
@@ -466,6 +465,7 @@ Upstreamed features *nvim-upstreamed*
These Nvim features were later integrated into Vim. These Nvim features were later integrated into Vim.
- 'diffopt' "linematch" feature
- 'fillchars' flags: "eob" - 'fillchars' flags: "eob"
- 'jumpoptions' "stack" behavior - 'jumpoptions' "stack" behavior
- 'wildoptions' flags: "pum" enables popupmenu for wildmode completion - 'wildoptions' flags: "pum" enables popupmenu for wildmode completion

View File

@@ -1631,11 +1631,20 @@ vim.go.dex = vim.go.diffexpr
--- Option settings for diff mode. It can consist of the following items. --- Option settings for diff mode. It can consist of the following items.
--- All are optional. Items must be separated by a comma. --- All are optional. Items must be separated by a comma.
--- ---
--- filler Show filler lines, to keep the text --- algorithm:{text} Use the specified diff algorithm with the
--- synchronized with a window that has inserted --- internal diff engine. Currently supported
--- lines at the same position. Mostly useful --- algorithms are:
--- when windows are side-by-side and 'scrollbind' --- myers the default algorithm
--- is set. --- minimal spend extra time to generate the
--- smallest possible diff
--- patience patience diff algorithm
--- histogram histogram diff algorithm
---
--- closeoff When a window is closed where 'diff' is set
--- and there is only one window remaining in the
--- same tab page with 'diff' set, execute
--- `:diffoff` in that window. This undoes a
--- `:diffsplit` command.
--- ---
--- context:{n} Use a context of {n} lines between a change --- context:{n} Use a context of {n} lines between a change
--- and a fold that contains unchanged lines. --- and a fold that contains unchanged lines.
@@ -1646,6 +1655,23 @@ vim.go.dex = vim.go.diffexpr
--- value (999999) to disable folding completely. --- value (999999) to disable folding completely.
--- See `fold-diff`. --- See `fold-diff`.
--- ---
--- filler Show filler lines, to keep the text
--- synchronized with a window that has inserted
--- lines at the same position. Mostly useful
--- when windows are side-by-side and 'scrollbind'
--- is set.
---
--- foldcolumn:{n} Set the 'foldcolumn' option to {n} when
--- starting diff mode. Without this 2 is used.
---
--- followwrap Follow the 'wrap' option and leave as it is.
---
--- horizontal Start diff mode with horizontal splits (unless
--- explicitly specified otherwise).
---
--- hiddenoff Do not use diff mode for a buffer when it
--- becomes hidden.
---
--- iblank Ignore changes where lines are all blank. Adds --- iblank Ignore changes where lines are all blank. Adds
--- the "-B" flag to the "diff" command if --- the "-B" flag to the "diff" command if
--- 'diffexpr' is empty. Check the documentation --- 'diffexpr' is empty. Check the documentation
@@ -1659,6 +1685,17 @@ vim.go.dex = vim.go.diffexpr
--- are considered the same. Adds the "-i" flag --- are considered the same. Adds the "-i" flag
--- to the "diff" command if 'diffexpr' is empty. --- to the "diff" command if 'diffexpr' is empty.
--- ---
--- indent-heuristic
--- Use the indent heuristic for the internal
--- diff library.
---
--- internal Use the internal diff library. This is
--- ignored when 'diffexpr' is set. *E960*
--- When running out of memory when writing a
--- buffer this item will be ignored for diffs
--- involving that buffer. Set the 'verbose'
--- option to see when this happens.
---
--- iwhite Ignore changes in amount of white space. Adds --- iwhite Ignore changes in amount of white space. Adds
--- the "-b" flag to the "diff" command if --- the "-b" flag to the "diff" command if
--- 'diffexpr' is empty. Check the documentation --- 'diffexpr' is empty. Check the documentation
@@ -1678,56 +1715,19 @@ vim.go.dex = vim.go.diffexpr
--- of the "diff" command for what this does --- of the "diff" command for what this does
--- exactly. --- exactly.
--- ---
--- horizontal Start diff mode with horizontal splits (unless --- linematch:{n} Align and mark changes between the most
--- explicitly specified otherwise). --- similar lines between the buffers. When the
--- total number of lines in the diff hunk exceeds
--- {n}, the lines will not be aligned because for
--- very large diff hunks there will be a
--- noticeable lag. A reasonable setting is
--- "linematch:60", as this will enable alignment
--- for a 2 buffer diff hunk of 30 lines each,
--- or a 3 buffer diff hunk of 20 lines each.
--- ---
--- vertical Start diff mode with vertical splits (unless --- vertical Start diff mode with vertical splits (unless
--- explicitly specified otherwise). --- explicitly specified otherwise).
--- ---
--- closeoff When a window is closed where 'diff' is set
--- and there is only one window remaining in the
--- same tab page with 'diff' set, execute
--- `:diffoff` in that window. This undoes a
--- `:diffsplit` command.
---
--- hiddenoff Do not use diff mode for a buffer when it
--- becomes hidden.
---
--- foldcolumn:{n} Set the 'foldcolumn' option to {n} when
--- starting diff mode. Without this 2 is used.
---
--- followwrap Follow the 'wrap' option and leave as it is.
---
--- internal Use the internal diff library. This is
--- ignored when 'diffexpr' is set. *E960*
--- When running out of memory when writing a
--- buffer this item will be ignored for diffs
--- involving that buffer. Set the 'verbose'
--- option to see when this happens.
---
--- indent-heuristic
--- Use the indent heuristic for the internal
--- diff library.
---
--- linematch:{n} Enable a second stage diff on each generated
--- hunk in order to align lines. When the total
--- number of lines in a hunk exceeds {n}, the
--- second stage diff will not be performed as
--- very large hunks can cause noticeable lag. A
--- recommended setting is "linematch:60", as this
--- will enable alignment for a 2 buffer diff with
--- hunks of up to 30 lines each, or a 3 buffer
--- diff with hunks of up to 20 lines each.
---
--- algorithm:{text} Use the specified diff algorithm with the
--- internal diff engine. Currently supported
--- algorithms are:
--- myers the default algorithm
--- minimal spend extra time to generate the
--- smallest possible diff
--- patience patience diff algorithm
--- histogram histogram diff algorithm
---
--- Examples: --- Examples:
--- ---
--- ```vim --- ```vim

View File

@@ -1820,7 +1820,8 @@ static void find_top_diff_block(diff_T **thistopdiff, diff_T **nextblockblock, i
topdiffchange = 0; topdiffchange = 0;
} }
// check if the fromwin topline is matched by the current diff. if so, set it to the top of the diff block // check if the fromwin topline is matched by the current diff. if so,
// set it to the top of the diff block
if (topline >= topdiff->df_lnum[fromidx] && topline <= if (topline >= topdiff->df_lnum[fromidx] && topline <=
(topdiff->df_lnum[fromidx] + topdiff->df_count[fromidx])) { (topdiff->df_lnum[fromidx] + topdiff->df_count[fromidx])) {
// this line is inside the current diff block, so we will save the // this line is inside the current diff block, so we will save the
@@ -2021,10 +2022,15 @@ static void run_linematch_algorithm(diff_T *dp)
size_t ndiffs = 0; size_t ndiffs = 0;
for (int i = 0; i < DB_COUNT; i++) { for (int i = 0; i < DB_COUNT; i++) {
if (curtab->tp_diffbuf[i] != NULL) { if (curtab->tp_diffbuf[i] != NULL) {
// write the contents of the entire buffer to if (dp->df_count[i] > 0) {
// diffbufs_mm[diffbuffers_count] // write the contents of the entire buffer to
diff_write_buffer(curtab->tp_diffbuf[i], &diffbufs_mm[ndiffs], // diffbufs_mm[diffbuffers_count]
dp->df_lnum[i], dp->df_lnum[i] + dp->df_count[i] - 1); diff_write_buffer(curtab->tp_diffbuf[i], &diffbufs_mm[ndiffs],
dp->df_lnum[i], dp->df_lnum[i] + dp->df_count[i] - 1);
} else {
diffbufs_mm[ndiffs].size = 0;
diffbufs_mm[ndiffs].ptr = NULL;
}
diffbufs[ndiffs] = &diffbufs_mm[ndiffs]; diffbufs[ndiffs] = &diffbufs_mm[ndiffs];
@@ -2060,6 +2066,12 @@ static void run_linematch_algorithm(diff_T *dp)
/// Returns > 0 for inserting that many filler lines above it (never happens /// Returns > 0 for inserting that many filler lines above it (never happens
/// when 'diffopt' doesn't contain "filler"). /// when 'diffopt' doesn't contain "filler").
/// This should only be used for windows where 'diff' is set. /// This should only be used for windows where 'diff' is set.
/// When diffopt contains linematch, a changed/added/deleted line
/// may also have filler lines above it. In such a case, the possibilities
/// are no longer mutually exclusive. The number of filler lines is
/// returned from diff_check, and the integer 'linestatus' passed by
/// pointer is set to -1 to indicate a changed line, and -2 to indicate an
/// added line
/// ///
/// @param wp /// @param wp
/// @param lnum /// @param lnum

View File

@@ -2178,11 +2178,20 @@ local options = {
Option settings for diff mode. It can consist of the following items. Option settings for diff mode. It can consist of the following items.
All are optional. Items must be separated by a comma. All are optional. Items must be separated by a comma.
filler Show filler lines, to keep the text algorithm:{text} Use the specified diff algorithm with the
synchronized with a window that has inserted internal diff engine. Currently supported
lines at the same position. Mostly useful algorithms are:
when windows are side-by-side and 'scrollbind' myers the default algorithm
is set. minimal spend extra time to generate the
smallest possible diff
patience patience diff algorithm
histogram histogram diff algorithm
closeoff When a window is closed where 'diff' is set
and there is only one window remaining in the
same tab page with 'diff' set, execute
`:diffoff` in that window. This undoes a
`:diffsplit` command.
context:{n} Use a context of {n} lines between a change context:{n} Use a context of {n} lines between a change
and a fold that contains unchanged lines. and a fold that contains unchanged lines.
@@ -2193,6 +2202,23 @@ local options = {
value (999999) to disable folding completely. value (999999) to disable folding completely.
See |fold-diff|. See |fold-diff|.
filler Show filler lines, to keep the text
synchronized with a window that has inserted
lines at the same position. Mostly useful
when windows are side-by-side and 'scrollbind'
is set.
foldcolumn:{n} Set the 'foldcolumn' option to {n} when
starting diff mode. Without this 2 is used.
followwrap Follow the 'wrap' option and leave as it is.
horizontal Start diff mode with horizontal splits (unless
explicitly specified otherwise).
hiddenoff Do not use diff mode for a buffer when it
becomes hidden.
iblank Ignore changes where lines are all blank. Adds iblank Ignore changes where lines are all blank. Adds
the "-B" flag to the "diff" command if the "-B" flag to the "diff" command if
'diffexpr' is empty. Check the documentation 'diffexpr' is empty. Check the documentation
@@ -2206,6 +2232,17 @@ local options = {
are considered the same. Adds the "-i" flag are considered the same. Adds the "-i" flag
to the "diff" command if 'diffexpr' is empty. to the "diff" command if 'diffexpr' is empty.
indent-heuristic
Use the indent heuristic for the internal
diff library.
internal Use the internal diff library. This is
ignored when 'diffexpr' is set. *E960*
When running out of memory when writing a
buffer this item will be ignored for diffs
involving that buffer. Set the 'verbose'
option to see when this happens.
iwhite Ignore changes in amount of white space. Adds iwhite Ignore changes in amount of white space. Adds
the "-b" flag to the "diff" command if the "-b" flag to the "diff" command if
'diffexpr' is empty. Check the documentation 'diffexpr' is empty. Check the documentation
@@ -2225,56 +2262,19 @@ local options = {
of the "diff" command for what this does of the "diff" command for what this does
exactly. exactly.
horizontal Start diff mode with horizontal splits (unless linematch:{n} Align and mark changes between the most
explicitly specified otherwise). similar lines between the buffers. When the
total number of lines in the diff hunk exceeds
{n}, the lines will not be aligned because for
very large diff hunks there will be a
noticeable lag. A reasonable setting is
"linematch:60", as this will enable alignment
for a 2 buffer diff hunk of 30 lines each,
or a 3 buffer diff hunk of 20 lines each.
vertical Start diff mode with vertical splits (unless vertical Start diff mode with vertical splits (unless
explicitly specified otherwise). explicitly specified otherwise).
closeoff When a window is closed where 'diff' is set
and there is only one window remaining in the
same tab page with 'diff' set, execute
`:diffoff` in that window. This undoes a
`:diffsplit` command.
hiddenoff Do not use diff mode for a buffer when it
becomes hidden.
foldcolumn:{n} Set the 'foldcolumn' option to {n} when
starting diff mode. Without this 2 is used.
followwrap Follow the 'wrap' option and leave as it is.
internal Use the internal diff library. This is
ignored when 'diffexpr' is set. *E960*
When running out of memory when writing a
buffer this item will be ignored for diffs
involving that buffer. Set the 'verbose'
option to see when this happens.
indent-heuristic
Use the indent heuristic for the internal
diff library.
linematch:{n} Enable a second stage diff on each generated
hunk in order to align lines. When the total
number of lines in a hunk exceeds {n}, the
second stage diff will not be performed as
very large hunks can cause noticeable lag. A
recommended setting is "linematch:60", as this
will enable alignment for a 2 buffer diff with
hunks of up to 30 lines each, or a 3 buffer
diff with hunks of up to 20 lines each.
algorithm:{text} Use the specified diff algorithm with the
internal diff engine. Currently supported
algorithms are:
myers the default algorithm
minimal spend extra time to generate the
smallest possible diff
patience patience diff algorithm
histogram histogram diff algorithm
Examples: >vim Examples: >vim
set diffopt=internal,filler,context:4 set diffopt=internal,filler,context:4
set diffopt= set diffopt=

View File

@@ -1017,6 +1017,41 @@ func Test_diff_screen()
call WriteDiffFiles(buf, [], [0]) call WriteDiffFiles(buf, [], [0])
call VerifyBoth(buf, "Test_diff_22", "") call VerifyBoth(buf, "Test_diff_22", "")
call WriteDiffFiles(buf, ['?a', '?b', '?c'], ['!b'])
call VerifyInternal(buf, 'Test_diff_23', " diffopt+=linematch:30")
call WriteDiffFiles(buf, ['',
\ 'common line',
\ 'common line',
\ '',
\ 'DEFabc',
\ 'xyz',
\ 'xyz',
\ 'xyz',
\ 'DEFabc',
\ 'DEFabc',
\ 'DEFabc',
\ 'common line',
\ 'common line',
\ 'DEF',
\ 'common line',
\ 'DEF',
\ 'something' ],
\ ['',
\ 'common line',
\ 'common line',
\ '',
\ 'ABCabc',
\ 'ABCabc',
\ 'ABCabc',
\ 'ABCabc',
\ 'common line',
\ 'common line',
\ 'common line',
\ 'something'])
call VerifyInternal(buf, 'Test_diff_24', " diffopt+=linematch:30")
" clean up " clean up
call StopVimInTerminal(buf) call StopVimInTerminal(buf)
call delete('Xdifile1') call delete('Xdifile1')
@@ -2040,4 +2075,411 @@ func Test_diff_topline_noscroll()
call term_sendkeys(buf, "\<C-W>p") call term_sendkeys(buf, "\<C-W>p")
call term_wait(buf) call term_wait(buf)
call VerifyScreenDump(buf, 'Test_diff_topline_4', {}) call VerifyScreenDump(buf, 'Test_diff_topline_4', {})
call StopVimInTerminal(buf)
endfunc
func Test_diffget_diffput_linematch()
CheckScreendump
call delete('.Xdifile1.swp')
call delete('.Xdifile2.swp')
call WriteDiffFiles(0, [], [])
let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
" enable linematch
call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
call WriteDiffFiles(buf, ['',
\ 'common line',
\ 'common line',
\ '',
\ 'ABCabc',
\ 'ABCabc',
\ 'ABCabc',
\ 'ABCabc',
\ 'common line',
\ 'common line',
\ 'common line',
\ 'something' ],
\ ['',
\ 'common line',
\ 'common line',
\ '',
\ 'DEFabc',
\ 'xyz',
\ 'xyz',
\ 'xyz',
\ 'DEFabc',
\ 'DEFabc',
\ 'DEFabc',
\ 'common line',
\ 'common line',
\ 'DEF',
\ 'common line',
\ 'DEF',
\ 'something'])
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_1', {})
" get from window 1 from line 5 to 9
call term_sendkeys(buf, "1\<c-w>w")
call term_sendkeys(buf, ":5,9diffget\<CR>")
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_2', {})
" undo the last diffget
call term_sendkeys(buf, "u")
" get from window 2 from line 5 to 10
call term_sendkeys(buf, "2\<c-w>w")
call term_sendkeys(buf, ":5,10diffget\<CR>")
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_3', {})
" undo the last diffget
call term_sendkeys(buf, "u")
" get all from window 2
call term_sendkeys(buf, "2\<c-w>w")
call term_sendkeys(buf, ":4,17diffget\<CR>")
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_4', {})
" undo the last diffget
call term_sendkeys(buf, "u")
" get all from window 1
call term_sendkeys(buf, "1\<c-w>w")
call term_sendkeys(buf, ":4,12diffget\<CR>")
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_5', {})
" undo the last diffget
call term_sendkeys(buf, "u")
" get from window 1 using do 1 line 5
call term_sendkeys(buf, "1\<c-w>w")
call term_sendkeys(buf, "5gg")
call term_sendkeys(buf, ":diffget\<CR>")
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_6', {})
" undo the last diffget
call term_sendkeys(buf, "u")
" get from window 1 using do 2 line 6
call term_sendkeys(buf, "1\<c-w>w")
call term_sendkeys(buf, "6gg")
call term_sendkeys(buf, ":diffget\<CR>")
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_7', {})
" undo the last diffget
call term_sendkeys(buf, "u")
" get from window 1 using do 2 line 7
call term_sendkeys(buf, "1\<c-w>w")
call term_sendkeys(buf, "7gg")
call term_sendkeys(buf, ":diffget\<CR>")
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_8', {})
" undo the last diffget
call term_sendkeys(buf, "u")
" get from window 1 using do 2 line 11
call term_sendkeys(buf, "1\<c-w>w")
call term_sendkeys(buf, "11gg")
call term_sendkeys(buf, ":diffget\<CR>")
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_9', {})
" undo the last diffget
call term_sendkeys(buf, "u")
" get from window 1 using do 2 line 12
call term_sendkeys(buf, "1\<c-w>w")
call term_sendkeys(buf, "12gg")
call term_sendkeys(buf, ":diffget\<CR>")
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_10', {})
" undo the last diffget
call term_sendkeys(buf, "u")
" put from window 1 using dp 1 line 5
call term_sendkeys(buf, "1\<c-w>w")
call term_sendkeys(buf, "5gg")
call term_sendkeys(buf, ":diffput\<CR>")
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_11', {})
" undo the last diffput
call term_sendkeys(buf, "2\<c-w>w")
call term_sendkeys(buf, "u")
" put from window 1 using dp 2 line 6
call term_sendkeys(buf, "1\<c-w>w")
call term_sendkeys(buf, "6gg")
call term_sendkeys(buf, ":diffput\<CR>")
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_12', {})
" undo the last diffput
call term_sendkeys(buf, "2\<c-w>w")
call term_sendkeys(buf, "u")
" put from window 1 using dp 2 line 7
call term_sendkeys(buf, "1\<c-w>w")
call term_sendkeys(buf, "7gg")
call term_sendkeys(buf, ":diffput\<CR>")
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_13', {})
" undo the last diffput
call term_sendkeys(buf, "2\<c-w>w")
call term_sendkeys(buf, "u")
" put from window 1 using dp 2 line 11
call term_sendkeys(buf, "1\<c-w>w")
call term_sendkeys(buf, "11gg")
call term_sendkeys(buf, ":diffput\<CR>")
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_14', {})
" undo the last diffput
call term_sendkeys(buf, "2\<c-w>w")
call term_sendkeys(buf, "u")
" put from window 1 using dp 2 line 12
call term_sendkeys(buf, "1\<c-w>w")
call term_sendkeys(buf, "12gg")
call term_sendkeys(buf, ":diffput\<CR>")
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_15', {})
" undo the last diffput
call term_sendkeys(buf, "2\<c-w>w")
call term_sendkeys(buf, "u")
" put from window 2 using dp line 6
call term_sendkeys(buf, "2\<c-w>w")
call term_sendkeys(buf, "6gg")
call term_sendkeys(buf, ":diffput\<CR>")
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_16', {})
" undo the last diffput
call term_sendkeys(buf, "1\<c-w>w")
call term_sendkeys(buf, "u")
" put from window 2 using dp line 8
call term_sendkeys(buf, "2\<c-w>w")
call term_sendkeys(buf, "8gg")
call term_sendkeys(buf, ":diffput\<CR>")
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_17', {})
" undo the last diffput
call term_sendkeys(buf, "1\<c-w>w")
call term_sendkeys(buf, "u")
" put from window 2 using dp line 9
call term_sendkeys(buf, "2\<c-w>w")
call term_sendkeys(buf, "9gg")
call term_sendkeys(buf, ":diffput\<CR>")
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_18', {})
" undo the last diffput
call term_sendkeys(buf, "1\<c-w>w")
call term_sendkeys(buf, "u")
" put from window 2 using dp line 17
call term_sendkeys(buf, "2\<c-w>w")
call term_sendkeys(buf, "17gg")
call term_sendkeys(buf, ":diffput\<CR>")
call VerifyScreenDump(buf, 'Test_diff_get_put_linematch_19', {})
endfunc
func Test_linematch_diff()
CheckScreendump
call delete('.Xdifile1.swp')
call delete('.Xdifile2.swp')
call WriteDiffFiles(0, [], [])
let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
" enable linematch
call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
call WriteDiffFiles(buf, ['// abc d?',
\ '// d?',
\ '// d?' ],
\ ['!',
\ 'abc d!',
\ 'd!'])
call VerifyScreenDump(buf, 'Test_linematch_diff1', {})
endfunc
func Test_linematch_diff_iwhite()
CheckScreendump
call delete('.Xdifile1.swp')
call delete('.Xdifile2.swp')
call WriteDiffFiles(0, [], [])
let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
" setup a diff with 2 files and set linematch:30, with ignore white
call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
call WriteDiffFiles(buf, ['void testFunction () {',
\ ' for (int i = 0; i < 10; i++) {',
\ ' for (int j = 0; j < 10; j++) {',
\ ' }',
\ ' }',
\ '}' ],
\ ['void testFunction () {',
\ ' // for (int j = 0; j < 10; i++) {',
\ ' // }',
\ '}'])
call VerifyScreenDump(buf, 'Test_linematch_diff_iwhite1', {})
call term_sendkeys(buf, ":set diffopt+=iwhiteall\<CR>")
call VerifyScreenDump(buf, 'Test_linematch_diff_iwhite2', {})
endfunc
func Test_linematch_diff_grouping()
CheckScreendump
call delete('.Xdifile1.swp')
call delete('.Xdifile2.swp')
call WriteDiffFiles(0, [], [])
let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
" a diff that would result in multiple groups before grouping optimization
call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
call WriteDiffFiles(buf, ['!A',
\ '!B',
\ '!C' ],
\ ['?Z',
\ '?A',
\ '?B',
\ '?C',
\ '?A',
\ '?B',
\ '?B',
\ '?C'])
call VerifyScreenDump(buf, 'Test_linematch_diff_grouping1', {})
call WriteDiffFiles(buf, ['!A',
\ '!B',
\ '!C' ],
\ ['?A',
\ '?Z',
\ '?B',
\ '?C',
\ '?A',
\ '?B',
\ '?C',
\ '?C'])
call VerifyScreenDump(buf, 'Test_linematch_diff_grouping2', {})
endfunc
func Test_linematch_diff_scroll()
CheckScreendump
call delete('.Xdifile1.swp')
call delete('.Xdifile2.swp')
call WriteDiffFiles(0, [], [])
let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
" a diff that would result in multiple groups before grouping optimization
call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
call WriteDiffFiles(buf, ['!A',
\ '!B',
\ '!C' ],
\ ['?A',
\ '?Z',
\ '?B',
\ '?C',
\ '?A',
\ '?B',
\ '?C',
\ '?C'])
" scroll down to show calculation of top fill and scroll to correct line in
" both windows
call VerifyScreenDump(buf, 'Test_linematch_diff_grouping_scroll0', {})
call term_sendkeys(buf, "3\<c-e>")
call VerifyScreenDump(buf, 'Test_linematch_diff_grouping_scroll1', {})
call term_sendkeys(buf, "3\<c-e>")
call VerifyScreenDump(buf, 'Test_linematch_diff_grouping_scroll2', {})
endfunc
func Test_linematch_line_limit_exceeded()
CheckScreendump
call delete('.Xdifile1.swp')
call delete('.Xdifile2.swp')
call WriteDiffFiles(0, [], [])
let buf = RunVimInTerminal('-d Xdifile1 Xdifile2', {})
call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
call term_sendkeys(buf, ":set diffopt+=linematch:10\<CR>")
" a diff block will not be aligned with linematch because it's contents
" exceed 10 lines
call WriteDiffFiles(buf,
\ ['common line',
\ 'HIL',
\ '',
\ 'aABCabc',
\ 'aABCabc',
\ 'aABCabc',
\ 'aABCabc',
\ 'common line',
\ 'HIL',
\ 'common line',
\ 'something'],
\ ['common line',
\ 'DEF',
\ 'GHI',
\ 'something',
\ '',
\ 'aDEFabc',
\ 'xyz',
\ 'xyz',
\ 'xyz',
\ 'aDEFabc',
\ 'aDEFabc',
\ 'aDEFabc',
\ 'common line',
\ 'DEF',
\ 'GHI',
\ 'something else',
\ 'common line',
\ 'something'])
call VerifyScreenDump(buf, 'Test_linematch_line_limit_exceeded1', {})
" after increasing the count to 30, the limit is not exceeded, and the
" alignment algorithm will run on the largest diff block here
call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
call VerifyScreenDump(buf, 'Test_linematch_line_limit_exceeded2', {})
endfunc
func Test_linematch_3diffs()
CheckScreendump
call delete('.Xdifile1.swp')
call delete('.Xdifile2.swp')
call delete('.Xdifile3.swp')
call WriteDiffFiles3(0, [], [], [])
let buf = RunVimInTerminal('-d Xdifile1 Xdifile2 Xdifile3', {})
call term_sendkeys(buf, "1\<c-w>w:set autoread\<CR>")
call term_sendkeys(buf, "2\<c-w>w:set autoread\<CR>")
call term_sendkeys(buf, "3\<c-w>w:set autoread\<CR>")
call term_sendkeys(buf, ":set diffopt+=linematch:30\<CR>")
call WriteDiffFiles3(buf,
\ ["",
\ " common line",
\ " AAA",
\ " AAA",
\ " AAA"],
\ ["",
\ " common line",
\ " <<<<<<< HEAD",
\ " AAA",
\ " AAA",
\ " AAA",
\ " =======",
\ " BBB",
\ " BBB",
\ " BBB",
\ " >>>>>>> branch1"],
\ ["",
\ " common line",
\ " BBB",
\ " BBB",
\ " BBB"])
call VerifyScreenDump(buf, 'Test_linematch_3diffs1', {}) call VerifyScreenDump(buf, 'Test_linematch_3diffs1', {})