Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions src/message.c
Original file line number Diff line number Diff line change
Expand Up @@ -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]))
Expand Down Expand Up @@ -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);
}
}
Expand Down
12 changes: 9 additions & 3 deletions src/screen.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
{
Expand Down
13 changes: 12 additions & 1 deletion src/testdir/test_listchars.vim
Original file line number Diff line number Diff line change
Expand Up @@ -390,34 +390,40 @@ 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
set listchars=tab:>-,leadtab:├─┤
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
set listchars=tab:>-,leadtab:+*,space:.
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
set listchars=tab:>-,leadtab:\|\
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
set listchars=tab:>-,leadtab:\
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.
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
12 changes: 7 additions & 5 deletions src/testdir/util/gen_opt_test.vim
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
Loading