aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2025-02-03 21:52:53 +0800
committerzeertzjq <zeertzjq@outlook.com>2025-02-04 08:42:53 +0800
commit290bb4c64bdcc475c29b857dc8626f5c51aa2b8d (patch)
treeaf9c68ab653a2cc24dc3d6b6993e0133f9590c50
parent5a7cf85c2c7e452563a4bce9195e9a3426ca3050 (diff)
downloadrneovim-290bb4c64bdcc475c29b857dc8626f5c51aa2b8d.tar.gz
rneovim-290bb4c64bdcc475c29b857dc8626f5c51aa2b8d.tar.bz2
rneovim-290bb4c64bdcc475c29b857dc8626f5c51aa2b8d.zip
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 https://github.com/vim/vim/commit/7c7a4e6d1ad50d5b25b42aa2d5a33a8d04a4cc8a Co-authored-by: Jonathon <jonathonwhite@protonmail.com>
-rw-r--r--runtime/doc/dev_vimpatch.txt1
-rw-r--r--runtime/doc/options.txt102
-rw-r--r--runtime/doc/vim_diff.txt2
-rw-r--r--runtime/lua/vim/_meta/options.lua102
-rw-r--r--src/nvim/diff.c22
-rw-r--r--src/nvim/options.lua102
-rw-r--r--test/old/testdir/test_diffmode.vim442
7 files changed, 614 insertions, 159 deletions
diff --git a/runtime/doc/dev_vimpatch.txt b/runtime/doc/dev_vimpatch.txt
index 76be24878a..0ddfc75a4c 100644
--- a/runtime/doc/dev_vimpatch.txt
+++ b/runtime/doc/dev_vimpatch.txt
@@ -184,6 +184,7 @@ information.
mch_memmove memmove
vim_memset copy_chars copy_spaces memset
vim_strbyte strchr
+ vim_strnchr strnchr
vim_strncpy strncpy xstrlcpy/xmemcpyz
vim_strcat strncat xstrlcat
VIM_ISWHITE ascii_iswhite
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index b4ae3cc8fd..4d186bd761 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -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.
All are optional. Items must be separated by a comma.
- 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.
+ 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
+
+ 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
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.
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
the "-B" flag to the "diff" command if
'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
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
the "-b" flag to the "diff" command if
'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
exactly.
- horizontal Start diff mode with horizontal splits (unless
- explicitly specified otherwise).
+ linematch:{n} Align and mark changes between the most
+ 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
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
set diffopt=internal,filler,context:4
set diffopt=
diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt
index c870de00ef..eae341da49 100644
--- a/runtime/doc/vim_diff.txt
+++ b/runtime/doc/vim_diff.txt
@@ -351,7 +351,6 @@ Options:
- 'autoread' works in the terminal (if it supports "focus" events)
- 'background' cannot be set to empty.
- 'cpoptions' flags: |cpo-_|
-- 'diffopt' "linematch" feature
- 'eadirection' cannot be set to empty.
- 'exrc' searches for ".nvim.lua", ".nvimrc", or ".exrc" files. The
user is prompted whether to trust the file.
@@ -466,6 +465,7 @@ Upstreamed features *nvim-upstreamed*
These Nvim features were later integrated into Vim.
+- 'diffopt' "linematch" feature
- 'fillchars' flags: "eob"
- 'jumpoptions' "stack" behavior
- 'wildoptions' flags: "pum" enables popupmenu for wildmode completion
diff --git a/runtime/lua/vim/_meta/options.lua b/runtime/lua/vim/_meta/options.lua
index 452959970d..52c556867f 100644
--- a/runtime/lua/vim/_meta/options.lua
+++ b/runtime/lua/vim/_meta/options.lua
@@ -1631,11 +1631,20 @@ vim.go.dex = vim.go.diffexpr
--- Option settings for diff mode. It can consist of the following items.
--- All are optional. Items must be separated by a comma.
---
---- 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.
+--- 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
+---
+--- 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
--- and a fold that contains unchanged lines.
@@ -1646,6 +1655,23 @@ vim.go.dex = vim.go.diffexpr
--- value (999999) to disable folding completely.
--- 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
--- the "-B" flag to the "diff" command if
--- 'diffexpr' is empty. Check the documentation
@@ -1659,6 +1685,17 @@ vim.go.dex = vim.go.diffexpr
--- are considered the same. Adds the "-i" flag
--- 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
--- the "-b" flag to the "diff" command if
--- 'diffexpr' is empty. Check the documentation
@@ -1678,56 +1715,19 @@ vim.go.dex = vim.go.diffexpr
--- of the "diff" command for what this does
--- exactly.
---
---- horizontal Start diff mode with horizontal splits (unless
---- explicitly specified otherwise).
+--- linematch:{n} Align and mark changes between the most
+--- 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
--- 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
diff --git a/src/nvim/diff.c b/src/nvim/diff.c
index 99f70793b3..4ead58c74f 100644
--- a/src/nvim/diff.c
+++ b/src/nvim/diff.c
@@ -1820,7 +1820,8 @@ static void find_top_diff_block(diff_T **thistopdiff, diff_T **nextblockblock, i
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 <=
(topdiff->df_lnum[fromidx] + topdiff->df_count[fromidx])) {
// 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;
for (int i = 0; i < DB_COUNT; i++) {
if (curtab->tp_diffbuf[i] != NULL) {
- // write the contents of the entire buffer to
- // diffbufs_mm[diffbuffers_count]
- diff_write_buffer(curtab->tp_diffbuf[i], &diffbufs_mm[ndiffs],
- dp->df_lnum[i], dp->df_lnum[i] + dp->df_count[i] - 1);
+ if (dp->df_count[i] > 0) {
+ // write the contents of the entire buffer to
+ // diffbufs_mm[diffbuffers_count]
+ 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];
@@ -2060,6 +2066,12 @@ static void run_linematch_algorithm(diff_T *dp)
/// Returns > 0 for inserting that many filler lines above it (never happens
/// when 'diffopt' doesn't contain "filler").
/// 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 lnum
diff --git a/src/nvim/options.lua b/src/nvim/options.lua
index fdd5799b46..4406ae28a8 100644
--- a/src/nvim/options.lua
+++ b/src/nvim/options.lua
@@ -2178,11 +2178,20 @@ local options = {
Option settings for diff mode. It can consist of the following items.
All are optional. Items must be separated by a comma.
- 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.
+ 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
+
+ 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
and a fold that contains unchanged lines.
@@ -2193,6 +2202,23 @@ local options = {
value (999999) to disable folding completely.
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
the "-B" flag to the "diff" command if
'diffexpr' is empty. Check the documentation
@@ -2206,6 +2232,17 @@ local options = {
are considered the same. Adds the "-i" flag
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
the "-b" flag to the "diff" command if
'diffexpr' is empty. Check the documentation
@@ -2225,56 +2262,19 @@ local options = {
of the "diff" command for what this does
exactly.
- horizontal Start diff mode with horizontal splits (unless
- explicitly specified otherwise).
+ linematch:{n} Align and mark changes between the most
+ 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
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
set diffopt=internal,filler,context:4
set diffopt=
diff --git a/test/old/testdir/test_diffmode.vim b/test/old/testdir/test_diffmode.vim
index 695aeeac75..b452be5061 100644
--- a/test/old/testdir/test_diffmode.vim
+++ b/test/old/testdir/test_diffmode.vim
@@ -1017,6 +1017,41 @@ func Test_diff_screen()
call WriteDiffFiles(buf, [], [0])
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
call StopVimInTerminal(buf)
call delete('Xdifile1')
@@ -2040,4 +2075,411 @@ func Test_diff_topline_noscroll()
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', {})
+
+endfunc
" vim: shiftwidth=2 sts=2 expandtab