From ba47cb7edab3cf90c171e7ef5a37e7ece46cd5e3 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Wed, 8 Oct 2025 06:51:15 +0800 Subject: [PATCH] vim-patch:9.1.1836: 'culopt' "screenline" not redrawn with line("w0") and :retab Problem: 'cursorlineopt' "screenline" isn't redrawn when moving cursor and then using line("w0") and :retab that does nothing. Solution: Call redraw_for_cursorcolumn() when setting a valid w_virtcol (zeertzjq). closes: vim/vim#18506 https://github.com/vim/vim/commit/a0849143614e687a305b6195dd8724840786e372 --- src/nvim/cursor.c | 6 +-- src/nvim/move.c | 9 ++++ src/nvim/window.c | 2 +- test/functional/ui/highlight_spec.lua | 60 ++++++++++++++++++--------- test/old/testdir/test_conceal.vim | 6 +++ test/old/testdir/test_cursorline.vim | 12 +++++- 6 files changed, 70 insertions(+), 25 deletions(-) diff --git a/src/nvim/cursor.c b/src/nvim/cursor.c index 421263e91e..adbd741b23 100644 --- a/src/nvim/cursor.c +++ b/src/nvim/cursor.c @@ -62,8 +62,7 @@ int coladvance_force(colnr_T wcol) curwin->w_valid &= ~VALID_VIRTCOL; } else { // Virtcol is valid - curwin->w_valid |= VALID_VIRTCOL; - curwin->w_virtcol = wcol; + set_valid_virtcol(curwin, wcol); } return rc; } @@ -83,8 +82,7 @@ int coladvance(win_T *wp, colnr_T wcol) wp->w_valid &= ~VALID_VIRTCOL; } else if (*(ml_get_buf(wp->w_buffer, wp->w_cursor.lnum) + wp->w_cursor.col) != TAB) { // Virtcol is valid when not on a TAB - wp->w_valid |= VALID_VIRTCOL; - wp->w_virtcol = wcol; + set_valid_virtcol(curwin, wcol); } return rc; } diff --git a/src/nvim/move.c b/src/nvim/move.c index 294c147838..20850c044e 100644 --- a/src/nvim/move.c +++ b/src/nvim/move.c @@ -179,6 +179,15 @@ static void redraw_for_cursorcolumn(win_T *wp) } } +/// Set wp->w_virtcol to a value ("vcol") that is already valid. +/// Handles redrawing if wp->w_virtcol was previously invalid. +void set_valid_virtcol(win_T *wp, colnr_T vcol) +{ + wp->w_virtcol = vcol; + redraw_for_cursorcolumn(wp); + wp->w_valid |= VALID_VIRTCOL; +} + /// Calculates how much the 'listchars' "precedes" or 'smoothscroll' "<<<" /// marker overlaps with buffer text for window "wp". /// Parameter "extra2" should be the padding on the 2nd line, not the first diff --git a/src/nvim/window.c b/src/nvim/window.c index 5c148ca9c7..7e085a111e 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6498,7 +6498,7 @@ void set_fraction(win_T *wp) /// calculate the new scroll position. /// TODO(vim): Ensure this also works with wrapped lines. /// Requires a not fully visible cursor line to be allowed at the bottom of -/// a window("zb"), probably only when 'smoothscroll' is also set. +/// a window ("zb"), probably only when 'smoothscroll' is also set. void win_fix_scroll(bool resize) { if (*p_spk == 'c') { diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua index 5e23492424..d6c47d9f1f 100644 --- a/test/functional/ui/highlight_spec.lua +++ b/test/functional/ui/highlight_spec.lua @@ -1065,25 +1065,6 @@ describe('CursorLine and CursorLineNr highlights', function() {101: }{100:>>>}aaaaaaaaaaaa | | ]]) - - command('inoremap call cursor(1, 1)') - feed('A') - screen:expect([[ - {103:0 }øøøøøøøøøøøøøøøøøø| - {101: }{100:>>>}{102:øøøøøøøøøøøø^ }| - {101:1 }aaaaaaaaaaaaaaaaaa| - {101: }{100:>>>}aaaaaaaaaaaa | - {5:-- INSERT --} | - ]]) - - feed('') - screen:expect([[ - {103:0 }{102:^øøøøøøøøøøøøøøøøøø}| - {101: }{100:>>>}øøøøøøøøøøøø | - {101:1 }aaaaaaaaaaaaaaaaaa| - {101: }{100:>>>}aaaaaaaaaaaa | - {5:-- INSERT --} | - ]]) end) -- oldtest: Test_cursorline_screenline_resize() @@ -1123,6 +1104,47 @@ describe('CursorLine and CursorLineNr highlights', function() ]]) end) + -- oldtest: Test_cursorline_screenline_update() + it("'cursorlineopt' screenline is updated on various movements", function() + local screen = Screen.new(75, 8) + exec([[ + func TestRetab() + let w = winwidth(0) + call cursor([1, w + 1, 0, w + 1]) + call line('w0') + retab 8 + endfunc + + call setline(1, repeat('xyz ', 30)) + set cursorline cursorlineopt=screenline tabstop=8 + inoremap call cursor(1, 1) + inoremap call TestRetab() + ]]) + + feed('A') + screen:expect([[ + xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz| + {21: xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz ^ }| + {1:~ }|*5 + {5:-- INSERT --} | + ]]) + feed('') + screen:expect([[ + {21:^xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz}| + xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz | + {1:~ }|*5 + {5:-- INSERT --} | + ]]) + feed('') + screen:expect([[ + xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz| + {21:^ xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz xyz }| + {1:~ }|*5 + {5:-- INSERT --} | + ]]) + feed('') + end) + -- oldtest: Test_cursorline_after_yank() it('always updated. vim-patch:8.1.0849', function() local screen = Screen.new(50, 5) diff --git a/test/old/testdir/test_conceal.vim b/test/old/testdir/test_conceal.vim index df20654f12..996276ed3f 100644 --- a/test/old/testdir/test_conceal.vim +++ b/test/old/testdir/test_conceal.vim @@ -394,6 +394,10 @@ func Test_conceal_mouse_click() syn match Concealed "this" conceal hi link Concealed Search + " Nvim: need to redraw before processing every key, because mouse clicks set + " w_redr_type, which prevent using vcols[]. + lua _G.NS = vim.on_key(function() vim.cmd.redraw() end) + " Test with both 'nocursorline' and 'cursorline', as they use two different " code paths to set virtual columns for the cells to clear. for cul in [v:false, v:true] @@ -550,6 +554,8 @@ func Test_conceal_mouse_click() setlocal number& signcolumn& endfor + lua vim.on_key(nil, _G.NS); _G.NS = nil + call CloseWindow() set mouse& endfunc diff --git a/test/old/testdir/test_cursorline.vim b/test/old/testdir/test_cursorline.vim index 2c375f20c0..4af85ede01 100644 --- a/test/old/testdir/test_cursorline.vim +++ b/test/old/testdir/test_cursorline.vim @@ -296,9 +296,17 @@ func Test_cursorline_screenline_update() CheckScreendump let lines =<< trim END + func TestRetab() + let w = winwidth(0) + call cursor([1, w + 1, 0, w + 1]) + call line('w0') + retab 8 + endfunc + call setline(1, repeat('xyz ', 30)) - set cursorline cursorlineopt=screenline + set cursorline cursorlineopt=screenline tabstop=8 inoremap call cursor(1, 1) + inoremap call TestRetab() END call writefile(lines, 'Xcul_screenline', 'D') @@ -307,6 +315,8 @@ func Test_cursorline_screenline_update() call VerifyScreenDump(buf, 'Test_cursorline_screenline_1', {}) call term_sendkeys(buf, "\") call VerifyScreenDump(buf, 'Test_cursorline_screenline_2', {}) + call term_sendkeys(buf, "\") + call VerifyScreenDump(buf, 'Test_cursorline_screenline_3', {}) call term_sendkeys(buf, "\") call StopVimInTerminal(buf)