From: zeertzjq Date: Tue, 3 Mar 2026 20:08:12 +0000 (+0000) Subject: patch 9.2.0102: 'listchars' "leadtab" not used in :list X-Git-Tag: v9.2.0102^0 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5845741d69655a731288ab105c8fd9fe46e12df9;p=thirdparty%2Fvim.git patch 9.2.0102: 'listchars' "leadtab" not used in :list Problem: 'listchars' "leadtab" not used in :list (after 9.2.0088). Solution: Also check for "leadtab" when using :list. Fix memory leak on E1572 if "multispace" or "leadmultispace" is set (zeertzjq). closes: #19557 Signed-off-by: zeertzjq Signed-off-by: Christian Brabandt --- diff --git a/src/message.c b/src/message.c index 78e5f30739..85beaa7c72 100644 --- a/src/message.c +++ b/src/message.c @@ -2066,7 +2066,8 @@ msg_prt_line(char_u *s, int list) } // find end of leading whitespace if (curwin->w_lcs_chars.lead - || curwin->w_lcs_chars.leadmultispace != NULL) + || curwin->w_lcs_chars.leadmultispace != NULL + || curwin->w_lcs_chars.leadtab1 != NUL) { lead = s; while (VIM_ISWHITE(lead[0])) @@ -2146,11 +2147,22 @@ msg_prt_line(char_u *s, int list) } else { - c = (n_extra == 0 && curwin->w_lcs_chars.tab3) - ? curwin->w_lcs_chars.tab3 - : curwin->w_lcs_chars.tab1; - c_extra = curwin->w_lcs_chars.tab2; - c_final = curwin->w_lcs_chars.tab3; + int lcs_tab1 = curwin->w_lcs_chars.tab1; + int lcs_tab2 = curwin->w_lcs_chars.tab2; + int lcs_tab3 = curwin->w_lcs_chars.tab3; + + // check if leadtab is set in 'listchars' + if (lead != NULL && s <= lead + && curwin->w_lcs_chars.leadtab1 != NUL) + { + lcs_tab1 = curwin->w_lcs_chars.leadtab1; + lcs_tab2 = curwin->w_lcs_chars.leadtab2; + lcs_tab3 = curwin->w_lcs_chars.leadtab3; + } + + c = (n_extra == 0 && lcs_tab3) ? lcs_tab3 : lcs_tab1; + c_extra = lcs_tab2; + c_final = lcs_tab3; attr = HL_ATTR(HLF_8); } } diff --git a/src/screen.c b/src/screen.c index 6a062ca263..1fb9a70aaf 100644 --- a/src/screen.c +++ b/src/screen.c @@ -5080,6 +5080,8 @@ set_chars_option(win_T *wp, char_u *value, int is_listchars, int apply, // first round: check for valid value, second round: assign values for (round = 0; round <= (apply ? 1 : 0); ++round) { + int has_tab = FALSE, has_leadtab = FALSE; + if (round > 0) { // After checking that the value is valid: set defaults. @@ -5247,6 +5249,10 @@ set_chars_option(win_T *wp, char_u *value, int is_listchars, int apply, e_wrong_character_width_for_field_str, tab[i].name.string); } + if (tab[i].cp == &lcs_chars.tab2) + has_tab = TRUE; + else // tab[i].cp == &lcs_chars.leadtab2 + has_leadtab = TRUE; } if (*s == ',' || *s == NUL) @@ -5283,10 +5289,10 @@ set_chars_option(win_T *wp, char_u *value, int is_listchars, int apply, if (*p == ',') ++p; } - } - if (is_listchars && lcs_chars.leadtab2 != NUL && lcs_chars.tab2 == NUL) - return e_leadtab_requires_tab; + if (is_listchars && has_leadtab && !has_tab) + return e_leadtab_requires_tab; + } if (apply) { diff --git a/src/testdir/test_listchars.vim b/src/testdir/test_listchars.vim index 9064b60275..fd0e146b23 100644 --- a/src/testdir/test_listchars.vim +++ b/src/testdir/test_listchars.vim @@ -390,6 +390,8 @@ func Test_listchars() \ 'text>---tab ' \ ] call Check_listchars(expected, 3, 20) + call assert_equal(expected->mapnew({_, s -> trim(s, ' ', 2)}) + [' '], + \ split(execute("%list"), "\n")) " Test leadtab with unicode characters normal ggdG @@ -397,6 +399,7 @@ func Test_listchars() call append(0, ["\ttext"]) let expected = ['├──────┤text'] call Check_listchars(expected, 1, 12) + call assert_equal(expected + [' '], split(execute("%list"), "\n")) " Test leadtab with mixed indentation (spaces + tabs) normal ggdG @@ -404,6 +407,7 @@ func Test_listchars() call append(0, [" \t text"]) let expected = ['.+******.text'] call Check_listchars(expected, 1, 13) + call assert_equal(expected + [' '], split(execute("%list"), "\n")) " Test leadtab with pipe character normal ggdG @@ -411,6 +415,7 @@ func Test_listchars() call append(0, ["\ttext"]) let expected = ['| text'] call Check_listchars(expected, 1, 12) + call assert_equal(expected + [' '], split(execute("%list"), "\n")) " Test leadtab with unicode bar normal ggdG @@ -418,6 +423,7 @@ func Test_listchars() call append(0, ["\ttext"]) let expected = ['│ text'] call Check_listchars(expected, 1, 12) + call assert_equal(expected + [' '], split(execute("%list"), "\n")) " Test leadtab vs tab distinction (leading vs non-leading) " In a line with only tabs, they aren't considered leading. @@ -436,6 +442,8 @@ func Test_listchars() \ '>------->------- ' \ ] call Check_listchars(expected, 4, 32) + call assert_equal(expected->mapnew({_, s -> trim(s, ' ', 2)}) + [' '], + \ split(execute("%list"), "\n")) " Test leadtab with trail and space normal ggdG @@ -451,6 +459,8 @@ func Test_listchars() \ '+*******..text<<' \ ] call Check_listchars(expected, 3, 16) + call assert_equal(expected->mapnew({_, s -> trim(s, ' ', 2)}) + [' '], + \ split(execute("%list"), "\n")) " Test leadtab with eol normal ggdG @@ -461,7 +471,8 @@ func Test_listchars() \ 'text>---tab$ ' \ ] call Check_listchars(expected, 2, 13) - + call assert_equal(expected->mapnew({_, s -> trim(s, ' ', 2)}) + ['$'], + \ split(execute("%list"), "\n")) " test nbsp normal ggdG diff --git a/src/testdir/util/gen_opt_test.vim b/src/testdir/util/gen_opt_test.vim index 0a010a9f4a..e1476001f3 100644 --- a/src/testdir/util/gen_opt_test.vim +++ b/src/testdir/util/gen_opt_test.vim @@ -247,11 +247,13 @@ let test_values = { \ ['xxx', ':none', 'xxx:', 'x:non', 'y:mok3', 'z:kittty']], \ 'langmap': [['', 'xX', 'aA,bB'], ['xxx']], \ 'lispoptions': [['', 'expr:0', 'expr:1'], ['xxx', 'expr:x', 'expr:']], - \ 'listchars': [['', 'eol:x', 'tab:xy', 'tab:xyz', 'space:x', - \ 'multispace:xxxy', 'lead:x', 'tab:xy,leadtab:xyz', 'leadmultispace:xxxy', - \ 'trail:x', 'extends:x', 'precedes:x', 'conceal:x', 'nbsp:x', - \ 'eol:\\x24', 'eol:\\u21b5', 'eol:\\U000021b5', 'eol:x,space:y'], - \ ['xxx', 'eol:', 'leadtab:xyz']], + \ 'listchars': [['', 'eol:x', 'tab:xy', 'tab:xyz', 'space:x', 'lead:x', + \ 'multispace:xxxy', 'tab:xy,leadtab:xyz', 'leadtab:xyz,tab:xy', + \ 'leadmultispace:xxxy', 'trail:x', 'extends:x', 'precedes:x', + \ 'conceal:x', 'eol:\\x24', 'eol:\\u21b5', 'eol:\\U000021b5', + \ 'eol:x,space:y', 'nbsp:x'], + \ ['xxx', 'eol:', 'leadtab:xyz', 'multispace:xxxy,leadtab:xyz', + \ 'leadmultispace:xxxy,leadtab:xyz,multispace:yyyx']], \ 'matchpairs': [['', '(:)', '(:),<:>'], ['xxx']], \ 'maxsearchcount': [[1, 10, 100, 1000], [0, -1, 10000]], \ 'messagesopt': [['hit-enter,history:1', 'hit-enter,history:10000', diff --git a/src/version.c b/src/version.c index ebf573e1aa..45c76d2670 100644 --- a/src/version.c +++ b/src/version.c @@ -734,6 +734,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 102, /**/ 101, /**/