From 02123bac0d821f3249d18ff4b4f84f98341e343d Mon Sep 17 00:00:00 2001 From: luukvbaal Date: Tue, 1 Apr 2025 07:56:36 +0200 Subject: [PATCH] fix(display): wrong cursor column with 'concealcursor' = "n" and virt_text (#33218) Problem: Inline virtual text placed in a decor provider callback invalidates `w_virtcol`, which must be valid for `win_line()`. Solution: Call `validate_virtcol()` after "line" decor provider callbacks. (cherry picked from commit 7e8b7bba21cfb0a35e442c27aec0ced1b32ce14d) --- src/nvim/drawline.c | 3 ++- test/functional/ui/decorations_spec.lua | 27 +++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 16e3a95121..6853e545e4 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -1151,7 +1151,8 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, b } } - decor_providers_invoke_line(wp, lnum - 1); + decor_providers_invoke_line(wp, lnum - 1); // may invalidate wp->w_virtcol + validate_virtcol(wp); has_decor = decor_redraw_line(wp, lnum - 1, &decor_state); diff --git a/test/functional/ui/decorations_spec.lua b/test/functional/ui/decorations_spec.lua index 5ef1ef54bb..4d31302f10 100644 --- a/test/functional/ui/decorations_spec.lua +++ b/test/functional/ui/decorations_spec.lua @@ -811,6 +811,33 @@ describe('decorations providers', function() | ]]) end) + + it('inline virt_text does not result in wrong cursor column #33153', function() + insert("line1 with a lot of text\nline2 with a lot of text") + setup_provider([[ + _G.do_win = false + vim.keymap.set('n', 'f', function() + _G.do_win = true + vim.cmd('redraw!') + end) + vim.o.concealcursor = 'n' + function on_do(event) + if event == 'win' and _G.do_win then + vim.api.nvim_buf_set_extmark(0, ns1, 1, 0, { + virt_text = { { 'virt_text ' } }, + virt_text_pos = 'inline' + }) + end + end + ]]) + feed('f') + screen:expect([[ + line1 with a lot of text | + virt_text line2 with a lot of tex^t | + {1:~ }|*5 + | + ]]) + end) end) describe('decoration_providers', function()