From 9966afbc9df4631ec3ed9464cf0d3c52e59d1702 Mon Sep 17 00:00:00 2001 From: Jaehwang Jung Date: Mon, 20 Apr 2026 01:29:31 +0900 Subject: [PATCH] fix(drawline): hang while redrawing diff filler above fold #39219 Problem: win_line() falls into infinite loop when a diff window has top filler above its first visible buffer line, that first visible buffer line is a closed fold, and the folded line uses normal non-empty foldtext. Solution: Allow flushing pending diff filler rows even when the underlying buffer line is folded with foldtext. AI-assisted: Codex Co-authored-by: zeertzjq (cherry picked from commit f2cc0a249d20462619801a194b67f6ab1d48476c) --- src/nvim/drawline.c | 2 +- test/functional/ui/fold_spec.lua | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index 0e571bece0..c8a0349e94 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -3105,7 +3105,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, b end_check: // At end of screen line and there is more to come: Display the line // so far. If there is no more to display it is caught above. - if (wlv.col >= view_width && (!has_foldtext || virt_line_index >= 0) + if (wlv.col >= view_width && (!has_foldtext || wlv.filler_todo > 0) && (wlv.col <= leftcols_width || *ptr != NUL || wlv.filler_todo > 0 diff --git a/test/functional/ui/fold_spec.lua b/test/functional/ui/fold_spec.lua index f65ff43ae8..aaff97fbe4 100644 --- a/test/functional/ui/fold_spec.lua +++ b/test/functional/ui/fold_spec.lua @@ -2978,6 +2978,29 @@ describe('folded lines', function() with_ext_multigrid(false) end) + it('does not hang drawing diff filler above a folded line', function() + Screen.new(80, 24) + exec([[ + call setline(1, ['fold', 'body']) + vnew + call setline(1, ['inserted', 'fold', 'body']) + + windo diffthis + wincmd l + setlocal foldmethod=manual + 1,2fold + normal! zM + + wincmd h + normal! 1Gzt + redraw + + let g:diff_filler_fold_done = 1 + ]]) + eq(1, api.nvim_get_var('diff_filler_fold_done')) + assert_alive() + end) + it("do not interfere with corrected cursor position for 'scrolloff'", function() local screen = Screen.new(40, 7) exec([[