From 518aa46158c56e75261ef095bdd313ade9197f46 Mon Sep 17 00:00:00 2001 From: zeertzjq Date: Tue, 3 Mar 2026 08:06:19 +0800 Subject: [PATCH] vim-patch:9.2.0090: "leadtab" behavior inconsistent on line with only TABs Problem: "leadtab" behavior inconsistent on line with only TABs (after 9.2.0088). Solution: Don't consider those as leading TABs. Also add more tests for existing behavior of "lead" and "leadmultispace" (zeertzjq). closes: vim/vim#19549 https://github.com/vim/vim/commit/4b30e40a1f0c27622f71e70648aff99a5a99be5f --- src/nvim/drawline.c | 2 +- test/old/testdir/test_listchars.vim | 85 ++++++++++++++++++++--------- 2 files changed, 59 insertions(+), 28 deletions(-) diff --git a/src/nvim/drawline.c b/src/nvim/drawline.c index c733e58355..97a741a57d 100644 --- a/src/nvim/drawline.c +++ b/src/nvim/drawline.c @@ -2426,7 +2426,7 @@ int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, int col_rows, b schar_T lcs_tab3 = wp->w_p_lcs_chars.tab3; // check if leadtab is set in 'listchars' if (wp->w_p_list && wp->w_p_lcs_chars.leadtab1 != NUL - && (leadcol == 0 || ptr < line + leadcol)) { + && ptr < line + leadcol) { lcs_tab1 = wp->w_p_lcs_chars.leadtab1; lcs_tab2 = wp->w_p_lcs_chars.leadtab2; lcs_tab3 = wp->w_p_lcs_chars.leadtab3; diff --git a/test/old/testdir/test_listchars.vim b/test/old/testdir/test_listchars.vim index 895ed0fb31..2191237576 100644 --- a/test/old/testdir/test_listchars.vim +++ b/test/old/testdir/test_listchars.vim @@ -153,6 +153,21 @@ func Test_listchars() call Check_listchars(expected, 5, -1, 6) call assert_equal(expected, split(execute("%list"), "\n")) + " In a line with only spaces, they aren't considered leading even if "trail" + " isn't set. + set listchars-=trail:< + let expected = [ + \ '>>>>ffffxxxx$', + \ '>>>>>>>>>>gg$', + \ 'hxxxxxxxxxxx$', + \ 'xxxxxxxxxxxx$', + \ '>>>>0xx0xxxx$', + \ '$' + \ ] + call Check_listchars(expected, 6) + call Check_listchars(expected, 5, -1, 6) + call assert_equal(expected, split(execute("%list"), "\n")) + " Test multispace normal ggdG set listchars=eol:$ " Accommodate Nvim default @@ -163,6 +178,7 @@ func Test_listchars() \ ' ffff ', \ ' i i gg', \ ' h ', + \ ' ', \ ' j ', \ ' 0 0 ', \ ]) @@ -171,12 +187,13 @@ func Test_listchars() \ 'yYzZffffyYzZ$', \ 'yYi iyYzZygg$', \ ' hyYzZyYzZyY$', + \ 'yYzZyYzZyYzZ$', \ 'yYzZyYzZyYj $', \ 'yYzZ0yY0yYzZ$', \ '$' \ ] - call Check_listchars(expected, 6) - call Check_listchars(expected, 5, -1, 6) + call Check_listchars(expected, 7) + call Check_listchars(expected, 6, -1, 6) call assert_equal(expected, split(execute("%list"), "\n")) " Test leadmultispace + multispace @@ -189,6 +206,7 @@ func Test_listchars() \ ' ffff ', \ ' i i  gg', \ ' h ', + \ ' ', \ ' j ', \ ' 0 0 ', \ ]) @@ -197,16 +215,17 @@ func Test_listchars() \ '.-+*ffffyYzZ$', \ '.-i iSyYzZgg$', \ ' hyYzZyYzZyY$', + \ 'yYzZyYzZyYzZ$', \ '.-+*.-+*.-j $', \ '.-+*0yY0yYzZ$', \ '$' \ ] call assert_equal('eol:$,multispace:yYzZ,nbsp:S,leadmultispace:.-+*', &listchars) - call Check_listchars(expected, 6) - call Check_listchars(expected, 5, -1, 1) - call Check_listchars(expected, 5, -1, 2) - call Check_listchars(expected, 5, -1, 3) - call Check_listchars(expected, 5, -1, 6) + call Check_listchars(expected, 7) + call Check_listchars(expected, 6, -1, 1) + call Check_listchars(expected, 6, -1, 2) + call Check_listchars(expected, 6, -1, 3) + call Check_listchars(expected, 6, -1, 6) call assert_equal(expected, split(execute("%list"), "\n")) " Test leadmultispace without multispace @@ -219,6 +238,7 @@ func Test_listchars() \ ' ffff ', \ ' i i gg', \ ' h ', + \ ' ', \ ' j ', \ ' 0 0 ', \ ]) @@ -227,16 +247,17 @@ func Test_listchars() \ '.-+*ffff>>>>$', \ '.-i+i+++++gg$', \ '+h>>>>>>>>>>$', + \ '>>>>>>>>>>>>$', \ '.-+*.-+*.-j>$', \ '.-+*0++0>>>>$', \ '$' \ ] call assert_equal('eol:$,nbsp:S,leadmultispace:.-+*,space:+,trail:>,eol:$', &listchars) - call Check_listchars(expected, 6) - call Check_listchars(expected, 5, -1, 1) - call Check_listchars(expected, 5, -1, 2) - call Check_listchars(expected, 5, -1, 3) - call Check_listchars(expected, 5, -1, 6) + call Check_listchars(expected, 7) + call Check_listchars(expected, 6, -1, 1) + call Check_listchars(expected, 6, -1, 2) + call Check_listchars(expected, 6, -1, 3) + call Check_listchars(expected, 6, -1, 6) call assert_equal(expected, split(execute("%list"), "\n")) " Test leadmultispace only @@ -249,6 +270,7 @@ func Test_listchars() \ ' ffff ', \ ' i i gg', \ ' h ', + \ ' ', \ ' j ', \ ' 0 0 ', \ ]) @@ -257,12 +279,13 @@ func Test_listchars() \ '.-+*ffff ', \ '.-i i gg', \ ' h ', + \ ' ', \ '.-+*.-+*.-j ', \ '.-+*0 0 ', \ ' ' \ ] call assert_equal('leadmultispace:.-+*', &listchars) - call Check_listchars(expected, 5, 12) + call Check_listchars(expected, 6, 12) call assert_equal(expected, split(execute("%list"), "\n")) " Changing the value of 'ambiwidth' twice shouldn't cause double-free when @@ -281,6 +304,7 @@ func Test_listchars() \ ' ffff ', \ ' i i gg', \ ' h ', + \ ' ', \ ' j ', \ ' 0 0 ', \ ]) @@ -289,16 +313,17 @@ func Test_listchars() \ '.-+*ffff----$', \ '.-i-i-----gg$', \ ',trail:< @@ -325,12 +351,13 @@ func Test_listchars() \ '>>>>ffff<<<<$', \ '>>ixiXyYXygg$', \ '>h<<<<<<<<<<$', + \ '<<<<<<<<<<<<$', \ '>>>>>>>>>>j<$', \ '>>>>0Xy0<<<<$', \ '$' \ ] - call Check_listchars(expected, 6) - call Check_listchars(expected, 5, -1, 6) + call Check_listchars(expected, 7) + call Check_listchars(expected, 6, -1, 6) call assert_equal(expected, split(execute("%list"), "\n")) " removing 'multispace:' @@ -341,12 +368,13 @@ func Test_listchars() \ '>>>>ffff<<<<$', \ '>>ixixxxxxgg$', \ '>h<<<<<<<<<<$', + \ '<<<<<<<<<<<<$', \ '>>>>>>>>>>j<$', \ '>>>>0xx0<<<<$', \ '$' \ ] - call Check_listchars(expected, 6) - call Check_listchars(expected, 5, -1, 6) + call Check_listchars(expected, 7) + call Check_listchars(expected, 6, -1, 6) call assert_equal(expected, split(execute("%list"), "\n")) " Test leadtab basic functionality @@ -394,19 +422,22 @@ func Test_listchars() call Check_listchars(expected, 1, 12) " Test leadtab vs tab distinction (leading vs non-leading) + " In a line with only tabs, they aren't considered leading. normal ggdG set listchars=tab:>-,leadtab:+* call append(0, [ \ "\tleading", \ "text\tnot leading", - \ "\t\tmultiple leading" + \ "\t\tmultiple leading", + \ "\t\t" \ ]) let expected = [ \ '+*******leading ', \ 'text>---not leading ', - \ '+*******+*******multiple leading' + \ '+*******+*******multiple leading', + \ '>------->------- ' \ ] - call Check_listchars(expected, 3, 32) + call Check_listchars(expected, 4, 32) " Test leadtab with trail and space normal ggdG