mirror of
https://github.com/neovim/neovim
synced 2025-07-16 01:01:49 +00:00
vim-patch:9.1.1439: Last diff folds not merged (#34380)
Problem: Last diff folds not merged (after v8.1.1922)
Solution: loop over all windows in the current tabpage and update all
folds (Gary Johnson)
This commit fixes a bug where the last two folds of a diff are not
merged when the last difference between the two diff'd buffers is
resolved.
Normally, when two buffers are diff'd, folding is used to show only the
text that differs and to hide the text that is the same between the two
buffers. When a difference is resolved by making a block of text the
same in both buffers, the folds are updated to merge that block with the
folds above and below it into one closed fold.
That updating of the folds did not occur when the block of text was the
last diff block in the buffers.
The bug was introduced by this patch on August 24, 2019:
patch 8.1.1922: in diff mode global operations can be very slow
Problem: In diff mode global operations can be very slow.
Solution: Do not call diff_redraw() many times, call it once when
redrawing. And also don't update folds multiple times.
Unfortunately, folds were then not updated often enough.
The problem was fixed by adding a short loop to the ex_diffgetput()
function in diff.c to update all the folds in the current tab when the
last difference is removed.
A test for this was added to test_diffmode.vim. Two of the reference
screen dumps for another test in that file,
Test_diffget_diffput_linematch(), had to be changed to have all the
folds closed rather than to have the last diff block remain open.
closes: vim/vim#17457
3fa0d3514b
Co-authored-by: Gary Johnson <garyjohn@spocom.com>
This commit is contained in:
@ -3552,6 +3552,15 @@ theend:
|
||||
check_cursor(curwin);
|
||||
changed_line_abv_curs();
|
||||
|
||||
// If all diffs are gone, update folds in all diff windows.
|
||||
if (curtab->tp_first_diff == NULL) {
|
||||
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
|
||||
if (wp->w_p_diff && wp->w_p_fdm[0] == 'd' && wp->w_p_fen) {
|
||||
foldUpdateAll(wp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (diff_need_update) {
|
||||
// redraw already done by ex_diffupdate()
|
||||
diff_need_update = false;
|
||||
|
@ -617,44 +617,15 @@ t3]])
|
||||
command('windo diffthis')
|
||||
feed('do')
|
||||
|
||||
screen:expect {
|
||||
grid = [[
|
||||
{1:+ }{2:+-- 9 lines: void ui_refresh(void)·······················}|
|
||||
{1: } for (size_t i = 0; i < ui_count; i++) { |
|
||||
{1: } UI *ui = uis[i]; |
|
||||
{1: } width = MIN(ui->width, width); |
|
||||
{1: } height = MIN(ui->height, height); |
|
||||
{1: } foo = BAR(ui->bazaar, bazaar); |
|
||||
{1: } for (UIExtension j = 0; (int)j < kUIExtCount; j++) { |
|
||||
{1: } ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
|
||||
{1: } } |
|
||||
{1: } } |
|
||||
{1: }} |
|
||||
{3:~ }|*6
|
||||
{4:[No Name] [+] }|
|
||||
{1:+ }{2:+-- 9 lines: void ui_refresh(void)·······················}|
|
||||
{1: } for (size_t i = 0; i < ui_count; i++) { |
|
||||
{1: } UI *ui = uis[i]; |
|
||||
{1: } width = MIN(ui->width, width); |
|
||||
{1: } height = MIN(ui->height, height); |
|
||||
{1: } foo = BAR(ui->bazaar, bazaar); |
|
||||
{1: } for (UIExtension j = 0; (int)j < kUIExtCount; j++) { |
|
||||
{1: } ext_widgets[j] &= (ui->ui_ext[j] || inclusive); |
|
||||
{1: } ^} |
|
||||
{1: } } |
|
||||
{1: }} |
|
||||
{3:~ }|*5
|
||||
{5:[No Name] [+] }|
|
||||
screen:expect([[
|
||||
{7:+ }{13:+-- 19 lines: void ui_refresh(void)·······················}|
|
||||
{1:~ }|*16
|
||||
{2:[No Name] [+] }|
|
||||
{7:+ }{13:^+-- 19 lines: void ui_refresh(void)·······················}|
|
||||
{1:~ }|*15
|
||||
{3:[No Name] [+] }|
|
||||
|
|
||||
]],
|
||||
attr_ids = {
|
||||
[1] = { background = Screen.colors.Grey, foreground = Screen.colors.Blue4 },
|
||||
[2] = { background = Screen.colors.LightGrey, foreground = Screen.colors.Blue4 },
|
||||
[3] = { foreground = Screen.colors.Blue, bold = true },
|
||||
[4] = { reverse = true },
|
||||
[5] = { reverse = true, bold = true },
|
||||
},
|
||||
}
|
||||
]])
|
||||
end)
|
||||
|
||||
it('does not extend closed fold with `o`/`O`', function()
|
||||
|
@ -303,19 +303,8 @@ something
|
||||
feed('2<c-w>w')
|
||||
feed(':4,17diffget<cr>')
|
||||
screen:expect([[
|
||||
{7: }{8: 1 } │{7: }{8: 1 }^ |
|
||||
{7: }{8: 2 }common line │{7: }{8: 2 }common line |
|
||||
{7: }{8: 3 }common line │{7: }{8: 3 }common line |
|
||||
{7: }{8: 4 } │{7: }{8: 4 } |
|
||||
{7: }{8: 5 }ABCabc │{7: }{8: 5 }ABCabc |
|
||||
{7: }{8: 6 }ABCabc │{7: }{8: 6 }ABCabc |
|
||||
{7: }{8: 7 }ABCabc │{7: }{8: 7 }ABCabc |
|
||||
{7: }{8: 8 }ABCabc │{7: }{8: 8 }ABCabc |
|
||||
{7: }{8: 9 }common line │{7: }{8: 9 }common line |
|
||||
{7: }{8: 10 }common line │{7: }{8: 10 }common line |
|
||||
{7: }{8: 11 }common line │{7: }{8: 11 }common line |
|
||||
{7: }{8: 12 }something │{7: }{8: 12 }something |
|
||||
{1:~ }│{1:~ }|*6
|
||||
{7:+ }{8: 1 }{13:+-- 12 lines: common line··················}│{7:+ }{8: 1 }{13:^+-- 12 lines: common line···················}|
|
||||
{1:~ }│{1:~ }|*17
|
||||
{2:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 [+] }|
|
||||
:4,17diffget |
|
||||
]])
|
||||
@ -324,24 +313,8 @@ something
|
||||
feed('1<c-w>w')
|
||||
feed(':4,12diffget<cr>')
|
||||
screen:expect([[
|
||||
{7: }{8: 1 }^ │{7: }{8: 1 } |
|
||||
{7: }{8: 2 }common line │{7: }{8: 2 }common line |
|
||||
{7: }{8: 3 }common line │{7: }{8: 3 }common line |
|
||||
{7: }{8: 4 } │{7: }{8: 4 } |
|
||||
{7: }{8: 5 }DEFabc │{7: }{8: 5 }DEFabc |
|
||||
{7: }{8: 6 }xyz │{7: }{8: 6 }xyz |
|
||||
{7: }{8: 7 }xyz │{7: }{8: 7 }xyz |
|
||||
{7: }{8: 8 }xyz │{7: }{8: 8 }xyz |
|
||||
{7: }{8: 9 }DEFabc │{7: }{8: 9 }DEFabc |
|
||||
{7: }{8: 10 }DEFabc │{7: }{8: 10 }DEFabc |
|
||||
{7: }{8: 11 }DEFabc │{7: }{8: 11 }DEFabc |
|
||||
{7: }{8: 12 }common line │{7: }{8: 12 }common line |
|
||||
{7: }{8: 13 }common line │{7: }{8: 13 }common line |
|
||||
{7: }{8: 14 }DEF │{7: }{8: 14 }DEF |
|
||||
{7: }{8: 15 }common line │{7: }{8: 15 }common line |
|
||||
{7: }{8: 16 }DEF │{7: }{8: 16 }DEF |
|
||||
{7: }{8: 17 }something │{7: }{8: 17 }something |
|
||||
{1:~ }│{1:~ }|
|
||||
{7:+ }{8: 1 }{13:^+-- 17 lines: common line··················}│{7:+ }{8: 1 }{13:+-- 17 lines: common line···················}|
|
||||
{1:~ }│{1:~ }|*17
|
||||
{3:Xtest-functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }|
|
||||
:4,12diffget |
|
||||
]])
|
||||
@ -968,24 +941,8 @@ something
|
||||
feed('2<c-w>w')
|
||||
feed(':1,12diffget<cr>')
|
||||
screen:expect([[
|
||||
{7: }{8: 1 }common line │{7: }{8: 1 }^common line |
|
||||
{7: }{8: 2 }DEF │{7: }{8: 2 }DEF |
|
||||
{7: }{8: 3 }GHI │{7: }{8: 3 }GHI |
|
||||
{7: }{8: 4 }something │{7: }{8: 4 }something |
|
||||
{7: }{8: 5 } │{7: }{8: 5 } |
|
||||
{7: }{8: 6 }aDEFabc │{7: }{8: 6 }aDEFabc |
|
||||
{7: }{8: 7 }xyz │{7: }{8: 7 }xyz |
|
||||
{7: }{8: 8 }xyz │{7: }{8: 8 }xyz |
|
||||
{7: }{8: 9 }xyz │{7: }{8: 9 }xyz |
|
||||
{7: }{8: 10 }aDEFabc │{7: }{8: 10 }aDEFabc |
|
||||
{7: }{8: 11 }aDEFabc │{7: }{8: 11 }aDEFabc |
|
||||
{7: }{8: 12 }aDEFabc │{7: }{8: 12 }aDEFabc |
|
||||
{7: }{8: 13 }common line │{7: }{8: 13 }common line |
|
||||
{7: }{8: 14 }DEF │{7: }{8: 14 }DEF |
|
||||
{7: }{8: 15 }GHI │{7: }{8: 15 }GHI |
|
||||
{7: }{8: 16 }something else │{7: }{8: 16 }something else |
|
||||
{7: }{8: 17 }common line │{7: }{8: 17 }common line |
|
||||
{7: }{8: 18 }something │{7: }{8: 18 }something |
|
||||
{7:+ }{8: 1 }{13:+-- 18 lines: common line··················}│{7:+ }{8: 1 }{13:^+-- 18 lines: common line···················}|
|
||||
{1:~ }│{1:~ }|*17
|
||||
{2:Xtest-functional-diff-screen-1.2 }{3:Xtest-functional-diff-screen-1 [+] }|
|
||||
:1,12diffget |
|
||||
]])
|
||||
@ -994,18 +951,8 @@ something
|
||||
feed('1<c-w>w')
|
||||
feed(':1,19diffget<cr>')
|
||||
screen:expect([[
|
||||
{7: }{8: 1 }^common line │{7: }{8: 1 }common line |
|
||||
{7: }{8: 2 }HIL │{7: }{8: 2 }HIL |
|
||||
{7: }{8: 3 } │{7: }{8: 3 } |
|
||||
{7: }{8: 4 }aABCabc │{7: }{8: 4 }aABCabc |
|
||||
{7: }{8: 5 }aABCabc │{7: }{8: 5 }aABCabc |
|
||||
{7: }{8: 6 }aABCabc │{7: }{8: 6 }aABCabc |
|
||||
{7: }{8: 7 }aABCabc │{7: }{8: 7 }aABCabc |
|
||||
{7: }{8: 8 }common line │{7: }{8: 8 }common line |
|
||||
{7: }{8: 9 }HIL │{7: }{8: 9 }HIL |
|
||||
{7: }{8: 10 }common line │{7: }{8: 10 }common line |
|
||||
{7: }{8: 11 }something │{7: }{8: 11 }something |
|
||||
{1:~ }│{1:~ }|*7
|
||||
{7:+ }{8: 1 }{13:^+-- 11 lines: common line··················}│{7:+ }{8: 1 }{13:+-- 11 lines: common line···················}|
|
||||
{1:~ }│{1:~ }|*17
|
||||
{3:Xtest-functional-diff-screen-1.2 [+] }{2:Xtest-functional-diff-screen-1 }|
|
||||
:1,19diffget |
|
||||
]])
|
||||
|
@ -50,6 +50,40 @@ func Test_vert_split()
|
||||
set diffopt&
|
||||
endfunc
|
||||
|
||||
" Test for diff folding redraw after last diff is resolved
|
||||
func Test_diff_fold_redraw()
|
||||
" Set up two files with the minimal case
|
||||
call writefile(['Paragraph 1', '', 'Paragraph 2', '', 'Paragraph 3'], 'Xfile1')
|
||||
call writefile(['Paragraph 1', '', 'Paragraph 3'], 'Xfile2')
|
||||
|
||||
" Open in diff mode
|
||||
exe 'edit Xfile1'
|
||||
exe 'vert diffsplit Xfile2'
|
||||
|
||||
" Ensure both windows are in diff mode and folds are enabled
|
||||
set foldmethod=diff
|
||||
set foldenable
|
||||
|
||||
" Go to the diff and apply dp to copy Paragraph 2 to Xfile2
|
||||
normal! ]c
|
||||
normal! dp
|
||||
|
||||
" Redraw and check folds
|
||||
redraw!
|
||||
let win1_fold = foldclosed(1)
|
||||
let win2_fold = foldclosed(1)
|
||||
|
||||
" Both windows should be fully folded (foldclosed returns 1 for top fold)
|
||||
call assert_equal(1, win1_fold)
|
||||
call assert_equal(1, win2_fold)
|
||||
|
||||
" Clean up
|
||||
bwipe!
|
||||
bwipe!
|
||||
call delete('Xfile1')
|
||||
call delete('Xfile2')
|
||||
endfunc
|
||||
|
||||
func Test_vert_split_internal()
|
||||
set diffopt=internal,filler
|
||||
call Common_vert_split()
|
||||
|
Reference in New Issue
Block a user