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

4b30e40a1f
This commit is contained in:
zeertzjq
2026-03-03 08:06:19 +08:00
parent 3e81072293
commit 518aa46158
2 changed files with 59 additions and 28 deletions

View File

@@ -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;

View File

@@ -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$',
\ '<h----------$',
\ '------------$',
\ '.-+*.-+*.-j-$',
\ '.-+*0--0----$',
\ '$'
\ ]
call assert_equal('eol:$,lead:<,space:-,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"))
" the last occurrence of 'multispace:' is used
@@ -310,13 +335,14 @@ func Test_listchars()
\ 'XyYXffffXyYX$',
\ 'XyixiXyYXygg$',
\ 'xhXyYXyYXyYX$',
\ 'XyYXyYXyYXyY$',
\ 'XyYXyYXyYXjx$',
\ 'XyYX0Xy0XyYX$',
\ '$'
\ ]
call assert_equal('eol:$,multispace:yYzZ,space:x,multispace:XyY', &listchars)
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"))
set listchars+=lead:>,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