mirror of
https://github.com/neovim/neovim.git
synced 2026-03-31 04:42:03 +00:00
vim-patch:9.1.1888: Wrong display with cpo+=$, matchparen and wrapped line (#36385)
Problem: Wrong display with cpo+=$, matchparen and wrapped line.
Solution: Use old cursor line height when scrolling with cpo+=$. Also
fix wrong redraw in non-current window. (zeertzjq)
fixes: vim/vim#18647
closes: vim/vim#18662
5c3e762631
This commit is contained in:
@@ -2035,12 +2035,11 @@ static void win_update(win_T *wp)
|
||||
// When at start of changed lines: May scroll following lines
|
||||
// up or down to minimize redrawing.
|
||||
// Don't do this when the change continues until the end.
|
||||
// Don't scroll when dollar_vcol >= 0, keep the "$".
|
||||
// Don't scroll when redrawing the top, scrolled already above.
|
||||
if (lnum == mod_top
|
||||
&& mod_bot != MAXLNUM
|
||||
&& !(dollar_vcol >= 0 && mod_bot == mod_top + 1)
|
||||
&& row >= top_end) {
|
||||
int old_cline_height = 0;
|
||||
int old_rows = 0;
|
||||
linenr_T l;
|
||||
int i;
|
||||
@@ -2055,6 +2054,9 @@ static void win_update(win_T *wp)
|
||||
&& wp->w_lines[i].wl_lnum == mod_bot) {
|
||||
break;
|
||||
}
|
||||
if (wp->w_lines[i].wl_lnum == wp->w_cursor.lnum) {
|
||||
old_cline_height = wp->w_lines[i].wl_size;
|
||||
}
|
||||
old_rows += wp->w_lines[i].wl_size;
|
||||
if (wp->w_lines[i].wl_valid
|
||||
&& wp->w_lines[i].wl_lastlnum + 1 == mod_bot) {
|
||||
@@ -2081,9 +2083,17 @@ static void win_update(win_T *wp)
|
||||
// rows, and may insert/delete lines
|
||||
int j = idx;
|
||||
for (l = lnum; l < mod_bot; l++) {
|
||||
int n = plines_correct_topline(wp, l, &l, true, NULL);
|
||||
new_rows += n;
|
||||
j += n > 0; // don't count concealed lines
|
||||
if (dollar_vcol >= 0 && wp == curwin
|
||||
&& old_cline_height > 0 && l == wp->w_cursor.lnum) {
|
||||
// When dollar_vcol >= 0, cursor line isn't fully
|
||||
// redrawn, and its height remains unchanged.
|
||||
new_rows += old_cline_height;
|
||||
j++;
|
||||
} else {
|
||||
int n = plines_correct_topline(wp, l, &l, true, NULL);
|
||||
new_rows += n;
|
||||
j += n > 0; // don't count concealed lines
|
||||
}
|
||||
if (new_rows > wp->w_view_height - row - 2) {
|
||||
// it's getting too much, must redraw the rest
|
||||
new_rows = 9999;
|
||||
@@ -2218,15 +2228,17 @@ static void win_update(win_T *wp)
|
||||
wp->w_lines[idx].wl_lnum = lnum;
|
||||
wp->w_lines[idx].wl_valid = true;
|
||||
|
||||
bool is_curline = wp == curwin && lnum == wp->w_cursor.lnum;
|
||||
|
||||
if (row > wp->w_view_height) { // past end of grid
|
||||
// we may need the size of that too long line later on
|
||||
if (dollar_vcol == -1) {
|
||||
if (dollar_vcol == -1 || !is_curline) {
|
||||
wp->w_lines[idx].wl_size = (uint16_t)plines_win(wp, lnum, true);
|
||||
}
|
||||
idx++;
|
||||
break;
|
||||
}
|
||||
if (dollar_vcol == -1) {
|
||||
if (dollar_vcol == -1 || !is_curline) {
|
||||
wp->w_lines[idx].wl_size = (uint16_t)(row - srow);
|
||||
}
|
||||
lnum = wp->w_lines[idx++].wl_lastlnum + 1;
|
||||
@@ -2343,7 +2355,7 @@ redr_statuscol:
|
||||
goto redr_statuscol;
|
||||
}
|
||||
}
|
||||
} else if (dollar_vcol == -1) {
|
||||
} else if (dollar_vcol == -1 || wp != curwin) {
|
||||
wp->w_botline = lnum;
|
||||
}
|
||||
|
||||
@@ -2385,7 +2397,7 @@ redr_statuscol:
|
||||
kv_A(win_extmark_arr, n).win_row, kv_A(win_extmark_arr, n).win_col);
|
||||
}
|
||||
|
||||
if (dollar_vcol == -1) {
|
||||
if (dollar_vcol == -1 || wp != curwin) {
|
||||
// There is a trick with w_botline. If we invalidate it on each
|
||||
// change that might modify it, this will cause a lot of expensive
|
||||
// calls to plines_win() in update_topline() each time. Therefore the
|
||||
|
||||
@@ -209,4 +209,213 @@ describe('display', function()
|
||||
|
|
||||
]])
|
||||
end)
|
||||
|
||||
-- oldtest: Test_change_wrapped_line_cpo_dollar()
|
||||
it('changing wrapped line with cpo+=$', function()
|
||||
local screen = Screen.new(45, 10)
|
||||
exec([[
|
||||
set cpoptions+=$ laststatus=0
|
||||
call setline(1, ['foo', 'bar',
|
||||
\ repeat('x', 25) .. '!!()!!' .. repeat('y', 25),
|
||||
\ 'FOO', 'BAR'])
|
||||
inoremap <F2> <Cmd>call setline(1, repeat('z', 30))<CR>
|
||||
inoremap <F3> <Cmd>call setline(1, 'foo')<CR>
|
||||
vsplit
|
||||
call cursor(3, 1)
|
||||
]])
|
||||
|
||||
local s1 = [[
|
||||
foo │foo |
|
||||
bar │bar |
|
||||
^xxxxxxxxxxxxxxxxxxxxxx│xxxxxxxxxxxxxxxxxxxxxx|
|
||||
xxx!!()!!yyyyyyyyyyyyy│xxx!!()!!yyyyyyyyyyyyy|
|
||||
yyyyyyyyyyyy │yyyyyyyyyyyy |
|
||||
FOO │FOO |
|
||||
BAR │BAR |
|
||||
{1:~ }│{1:~ }|*2
|
||||
|
|
||||
]]
|
||||
screen:expect(s1)
|
||||
feed('ct!')
|
||||
local s2 = [[
|
||||
foo │foo |
|
||||
bar │bar |
|
||||
^xxxxxxxxxxxxxxxxxxxxxx│!!()!!yyyyyyyyyyyyyyyy|
|
||||
xx$!!()!!yyyyyyyyyyyyy│yyyyyyyyy |
|
||||
yyyyyyyyyyyy │FOO |
|
||||
FOO │BAR |
|
||||
BAR │{1:~ }|
|
||||
{1:~ }│{1:~ }|*2
|
||||
{5:-- INSERT --} |
|
||||
]]
|
||||
screen:expect(s2)
|
||||
feed('<F2>')
|
||||
screen:expect([[
|
||||
zzzzzzzzzzzzzzzzzzzzzz│zzzzzzzzzzzzzzzzzzzzzz|
|
||||
zzzzzzzz │zzzzzzzz |
|
||||
bar │bar |
|
||||
^xxxxxxxxxxxxxxxxxxxxxx│!!()!!yyyyyyyyyyyyyyyy|
|
||||
xx$!!()!!yyyyyyyyyyyyy│yyyyyyyyy |
|
||||
yyyyyyyyyyyy │FOO |
|
||||
FOO │BAR |
|
||||
BAR │{1:~ }|
|
||||
{1:~ }│{1:~ }|
|
||||
{5:-- INSERT --} |
|
||||
]])
|
||||
feed('<F3>')
|
||||
screen:expect(s2)
|
||||
feed('y')
|
||||
screen:expect([[
|
||||
foo │foo |
|
||||
bar │bar |
|
||||
y^xxxxxxxxxxxxxxxxxxxxx│y!!()!!yyyyyyyyyyyyyyy|
|
||||
xx$!!()!!yyyyyyyyyyyyy│yyyyyyyyyy |
|
||||
yyyyyyyyyyyy │FOO |
|
||||
FOO │BAR |
|
||||
BAR │{1:~ }|
|
||||
{1:~ }│{1:~ }|*2
|
||||
{5:-- INSERT --} |
|
||||
]])
|
||||
feed('y')
|
||||
screen:expect([[
|
||||
foo │foo |
|
||||
bar │bar |
|
||||
yy^xxxxxxxxxxxxxxxxxxxx│yy!!()!!yyyyyyyyyyyyyy|
|
||||
xx$!!()!!yyyyyyyyyyyyy│yyyyyyyyyyy |
|
||||
yyyyyyyyyyyy │FOO |
|
||||
FOO │BAR |
|
||||
BAR │{1:~ }|
|
||||
{1:~ }│{1:~ }|*2
|
||||
{5:-- INSERT --} |
|
||||
]])
|
||||
feed('<Esc>')
|
||||
screen:expect([[
|
||||
foo │foo |
|
||||
bar │bar |
|
||||
y^y!!()!!yyyyyyyyyyyyyy│yy!!()!!yyyyyyyyyyyyyy|
|
||||
yyyyyyyyyyy │yyyyyyyyyyy |
|
||||
FOO │FOO |
|
||||
BAR │BAR |
|
||||
{1:~ }│{1:~ }|*3
|
||||
|
|
||||
]])
|
||||
|
||||
command('silent undo')
|
||||
screen:expect(s1)
|
||||
command('source test/old/testdir/samples/matchparen.vim')
|
||||
feed('ct(')
|
||||
screen:expect([[
|
||||
foo │foo |
|
||||
bar │bar |
|
||||
^xxxxxxxxxxxxxxxxxxxxxx│()!!yyyyyyyyyyyyyyyyyy|
|
||||
xxx!$()!!yyyyyyyyyyyyy│yyyyyyy |
|
||||
yyyyyyyyyyyy │FOO |
|
||||
FOO │BAR |
|
||||
BAR │{1:~ }|
|
||||
{1:~ }│{1:~ }|*2
|
||||
{5:-- INSERT --} |
|
||||
]])
|
||||
feed('y')
|
||||
screen:expect([[
|
||||
foo │foo |
|
||||
bar │bar |
|
||||
y^xxxxxxxxxxxxxxxxxxxxx│y()!!yyyyyyyyyyyyyyyyy|
|
||||
xxx!$()!!yyyyyyyyyyyyy│yyyyyyyy |
|
||||
yyyyyyyyyyyy │FOO |
|
||||
FOO │BAR |
|
||||
BAR │{1:~ }|
|
||||
{1:~ }│{1:~ }|*2
|
||||
{5:-- INSERT --} |
|
||||
]])
|
||||
feed('y')
|
||||
screen:expect([[
|
||||
foo │foo |
|
||||
bar │bar |
|
||||
yy^xxxxxxxxxxxxxxxxxxxx│yy()!!yyyyyyyyyyyyyyyy|
|
||||
xxx!$()!!yyyyyyyyyyyyy│yyyyyyyyy |
|
||||
yyyyyyyyyyyy │FOO |
|
||||
FOO │BAR |
|
||||
BAR │{1:~ }|
|
||||
{1:~ }│{1:~ }|*2
|
||||
{5:-- INSERT --} |
|
||||
]])
|
||||
feed('<Esc>')
|
||||
screen:expect([[
|
||||
foo │foo |
|
||||
bar │bar |
|
||||
y^y()!!yyyyyyyyyyyyyyyy│yy()!!yyyyyyyyyyyyyyyy|
|
||||
yyyyyyyyy │yyyyyyyyy |
|
||||
FOO │FOO |
|
||||
BAR │BAR |
|
||||
{1:~ }│{1:~ }|*3
|
||||
|
|
||||
]])
|
||||
|
||||
command('silent undo')
|
||||
screen:expect(s1)
|
||||
feed('f(azz<CR>zz<Esc>k0')
|
||||
screen:expect([[
|
||||
foo │foo |
|
||||
bar │bar |
|
||||
^xxxxxxxxxxxxxxxxxxxxxx│xxxxxxxxxxxxxxxxxxxxxx|
|
||||
xxx!!(zz │xxx!!(zz |
|
||||
zz)!!yyyyyyyyyyyyyyyyy│zz)!!yyyyyyyyyyyyyyyyy|
|
||||
yyyyyyyy │yyyyyyyy |
|
||||
FOO │FOO |
|
||||
BAR │BAR |
|
||||
{1:~ }│{1:~ }|
|
||||
|
|
||||
]])
|
||||
feed('ct(')
|
||||
screen:expect([[
|
||||
foo │foo |
|
||||
bar │bar |
|
||||
^xxxxxxxxxxxxxxxxxxxxxx│(zz |
|
||||
xxx!$(zz │zz)!!yyyyyyyyyyyyyyyyy|
|
||||
zz)!!yyyyyyyyyyyyyyyyy│yyyyyyyy |
|
||||
yyyyyyyy │FOO |
|
||||
FOO │BAR |
|
||||
BAR │{1:~ }|
|
||||
{1:~ }│{1:~ }|
|
||||
{5:-- INSERT --} |
|
||||
]])
|
||||
feed('y')
|
||||
screen:expect([[
|
||||
foo │foo |
|
||||
bar │bar |
|
||||
y^xxxxxxxxxxxxxxxxxxxxx│y(zz |
|
||||
xxx!$(zz │zz)!!yyyyyyyyyyyyyyyyy|
|
||||
zz)!!yyyyyyyyyyyyyyyyy│yyyyyyyy |
|
||||
yyyyyyyy │FOO |
|
||||
FOO │BAR |
|
||||
BAR │{1:~ }|
|
||||
{1:~ }│{1:~ }|
|
||||
{5:-- INSERT --} |
|
||||
]])
|
||||
feed('y')
|
||||
screen:expect([[
|
||||
foo │foo |
|
||||
bar │bar |
|
||||
yy^xxxxxxxxxxxxxxxxxxxx│yy(zz |
|
||||
xxx!$(zz │zz)!!yyyyyyyyyyyyyyyyy|
|
||||
zz)!!yyyyyyyyyyyyyyyyy│yyyyyyyy |
|
||||
yyyyyyyy │FOO |
|
||||
FOO │BAR |
|
||||
BAR │{1:~ }|
|
||||
{1:~ }│{1:~ }|
|
||||
{5:-- INSERT --} |
|
||||
]])
|
||||
feed('<Esc>')
|
||||
screen:expect([[
|
||||
foo │foo |
|
||||
bar │bar |
|
||||
y^y(zz │yy(zz |
|
||||
zz)!!yyyyyyyyyyyyyyyyy│zz)!!yyyyyyyyyyyyyyyyy|
|
||||
yyyyyyyy │yyyyyyyy |
|
||||
FOO │FOO |
|
||||
BAR │BAR |
|
||||
{1:~ }│{1:~ }|*2
|
||||
|
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
@@ -573,4 +573,65 @@ func Test_display_cursor_long_line()
|
||||
call StopVimInTerminal(buf)
|
||||
endfunc
|
||||
|
||||
func Test_change_wrapped_line_cpo_dollar()
|
||||
CheckScreendump
|
||||
|
||||
let lines =<< trim END
|
||||
set cpoptions+=$ laststatus=0
|
||||
call setline(1, ['foo', 'bar',
|
||||
\ repeat('x', 25) .. '!!()!!' .. repeat('y', 25),
|
||||
\ 'FOO', 'BAR'])
|
||||
inoremap <F2> <Cmd>call setline(1, repeat('z', 30))<CR>
|
||||
inoremap <F3> <Cmd>call setline(1, 'foo')<CR>
|
||||
vsplit
|
||||
call cursor(3, 1)
|
||||
END
|
||||
call writefile(lines, 'Xwrapped_cpo_dollar', 'D')
|
||||
let buf = RunVimInTerminal('-S Xwrapped_cpo_dollar', #{rows: 10, cols: 45})
|
||||
|
||||
call VerifyScreenDump(buf, 'Test_change_wrapped_line_cpo_dollar_01', {})
|
||||
call term_sendkeys(buf, 'ct!')
|
||||
call VerifyScreenDump(buf, 'Test_change_wrapped_line_cpo_dollar_02', {})
|
||||
call term_sendkeys(buf, "\<F2>")
|
||||
call VerifyScreenDump(buf, 'Test_change_wrapped_line_cpo_dollar_03', {})
|
||||
call term_sendkeys(buf, "\<F3>")
|
||||
call VerifyScreenDump(buf, 'Test_change_wrapped_line_cpo_dollar_02', {})
|
||||
call term_sendkeys(buf, 'y')
|
||||
call VerifyScreenDump(buf, 'Test_change_wrapped_line_cpo_dollar_04', {})
|
||||
call term_sendkeys(buf, 'y')
|
||||
call VerifyScreenDump(buf, 'Test_change_wrapped_line_cpo_dollar_05', {})
|
||||
call term_sendkeys(buf, "\<Esc>")
|
||||
call TermWait(buf, 50)
|
||||
call VerifyScreenDump(buf, 'Test_change_wrapped_line_cpo_dollar_06', {})
|
||||
|
||||
call term_sendkeys(buf, ":silent undo | echo\<CR>")
|
||||
call VerifyScreenDump(buf, 'Test_change_wrapped_line_cpo_dollar_01', {})
|
||||
call term_sendkeys(buf, ":source samples/matchparen.vim\<CR>")
|
||||
call term_sendkeys(buf, 'ct(')
|
||||
call VerifyScreenDump(buf, 'Test_change_wrapped_line_cpo_dollar_07', {})
|
||||
call term_sendkeys(buf, 'y')
|
||||
call VerifyScreenDump(buf, 'Test_change_wrapped_line_cpo_dollar_08', {})
|
||||
call term_sendkeys(buf, 'y')
|
||||
call VerifyScreenDump(buf, 'Test_change_wrapped_line_cpo_dollar_09', {})
|
||||
call term_sendkeys(buf, "\<Esc>")
|
||||
call TermWait(buf, 50)
|
||||
call VerifyScreenDump(buf, 'Test_change_wrapped_line_cpo_dollar_10', {})
|
||||
|
||||
call term_sendkeys(buf, ":silent undo | echo\<CR>")
|
||||
call VerifyScreenDump(buf, 'Test_change_wrapped_line_cpo_dollar_01', {})
|
||||
call term_sendkeys(buf, "f(azz\<CR>zz\<Esc>k0")
|
||||
call VerifyScreenDump(buf, 'Test_change_wrapped_line_cpo_dollar_11', {})
|
||||
call term_sendkeys(buf, 'ct(')
|
||||
call VerifyScreenDump(buf, 'Test_change_wrapped_line_cpo_dollar_12', {})
|
||||
call term_sendkeys(buf, 'y')
|
||||
call VerifyScreenDump(buf, 'Test_change_wrapped_line_cpo_dollar_13', {})
|
||||
call term_sendkeys(buf, 'y')
|
||||
call VerifyScreenDump(buf, 'Test_change_wrapped_line_cpo_dollar_14', {})
|
||||
call term_sendkeys(buf, "\<Esc>")
|
||||
call TermWait(buf, 50)
|
||||
call VerifyScreenDump(buf, 'Test_change_wrapped_line_cpo_dollar_15', {})
|
||||
|
||||
call StopVimInTerminal(buf)
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
Reference in New Issue
Block a user