vim-patch:8.2.2454: leading space can not be made visible (#14138)

Problem:    Leading space can not be made visible.
Solution:   Add "lead:" to 'listchars'. (closes vim/vim#7772)
91478ae49a
This commit is contained in:
zeertzjq 2021-03-30 09:26:11 +08:00 committed by GitHub
parent 291f1ece7f
commit f89bfa6869
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 78 additions and 7 deletions

View File

@ -3716,6 +3716,10 @@ A jump table for the options with a short description can be found at |Q_op|.
*lcs-space*
space:c Character to show for a space. When omitted, spaces
are left blank.
*lcs-lead*
lead:c Character to show for leading spaces. When omitted,
leading spaces are blank. Overrides the "space"
setting for leading spaces.
*lcs-trail*
trail:c Character to show for trailing spaces. When omitted,
trailing spaces are blank. Overrides the "space"

View File

@ -1201,6 +1201,7 @@ struct window_S {
int tab1; ///< first tab character
int tab2; ///< second tab character
int tab3; ///< third tab character
int lead;
int trail;
int conceal;
} w_p_lcs_chars;

View File

@ -1705,6 +1705,7 @@ void msg_prt_line(char_u *s, int list)
char_u *p_extra = NULL; // init to make SASC shut up
int n;
int attr = 0;
char_u *lead = NULL;
char_u *trail = NULL;
int l;
@ -1712,11 +1713,24 @@ void msg_prt_line(char_u *s, int list)
list = true;
}
// find start of trailing whitespace
if (list && curwin->w_p_lcs_chars.trail) {
trail = s + STRLEN(s);
while (trail > s && ascii_iswhite(trail[-1])) {
trail--;
if (list) {
// find start of trailing whitespace
if (curwin->w_p_lcs_chars.trail) {
trail = s + STRLEN(s);
while (trail > s && ascii_iswhite(trail[-1])) {
trail--;
}
}
// find end of leading whitespace
if (curwin->w_p_lcs_chars.lead) {
lead = s;
while (ascii_iswhite(lead[0])) {
lead++;
}
// in a line full of spaces all of them are treated as trailing
if (*lead == NUL) {
lead = NULL;
}
}
}
@ -1793,6 +1807,9 @@ void msg_prt_line(char_u *s, int list)
/* Use special coloring to be able to distinguish <hex> from
* the same in plain text. */
attr = HL_ATTR(HLF_8);
} else if (c == ' ' && lead != NULL && s <= lead) {
c = curwin->w_p_lcs_chars.lead;
attr = HL_ATTR(HLF_8);
} else if (c == ' ' && trail != NULL && s > trail) {
c = curwin->w_p_lcs_chars.trail;
attr = HL_ATTR(HLF_8);

View File

@ -3477,6 +3477,7 @@ static char_u *set_chars_option(win_T *wp, char_u **varp, bool set)
{ &wp->w_p_lcs_chars.prec, "precedes", NUL },
{ &wp->w_p_lcs_chars.space, "space", NUL },
{ &wp->w_p_lcs_chars.tab2, "tab", NUL },
{ &wp->w_p_lcs_chars.lead, "lead", NUL },
{ &wp->w_p_lcs_chars.trail, "trail", NUL },
{ &wp->w_p_lcs_chars.conceal, "conceal", NUL },
};

View File

@ -2082,6 +2082,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
int change_start = MAXCOL; // first col of changed area
int change_end = -1; // last col of changed area
colnr_T trailcol = MAXCOL; // start of trailing spaces
colnr_T leadcol = 0; // start of leading spaces
bool need_showbreak = false; // overlong line, skip first x chars
int line_attr = 0; // attribute for the whole line
int line_attr_lowprio = 0; // low-priority attribute for the line
@ -2427,6 +2428,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
if (wp->w_p_list && !has_fold) {
if (wp->w_p_lcs_chars.space
|| wp->w_p_lcs_chars.trail
|| wp->w_p_lcs_chars.lead
|| wp->w_p_lcs_chars.nbsp) {
extra_check = true;
}
@ -2438,6 +2440,20 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
trailcol += (colnr_T) (ptr - line);
}
// find end of leading whitespace
if (wp->w_p_lcs_chars.lead) {
leadcol = 0;
while (ascii_iswhite(ptr[leadcol])) {
leadcol++;
}
if (ptr[leadcol] == NUL) {
// in a line full of spaces all of them are treated as trailing
leadcol = (colnr_T)0;
} else {
// keep track of the first column not filled with spaces
leadcol += (colnr_T)(ptr - line) + 1;
}
}
}
/*
@ -3462,6 +3478,7 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
|| (mb_utf8 && (mb_c == 160 || mb_c == 0x202f)))
&& curwin->w_p_lcs_chars.nbsp)
|| (c == ' ' && curwin->w_p_lcs_chars.space
&& ptr - line >= leadcol
&& ptr - line <= trailcol))) {
c = (c == ' ') ? wp->w_p_lcs_chars.space : wp->w_p_lcs_chars.nbsp;
n_attr = 1;
@ -3477,8 +3494,10 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow,
}
}
if (trailcol != MAXCOL && ptr > line + trailcol && c == ' ') {
c = wp->w_p_lcs_chars.trail;
if ((trailcol != MAXCOL && ptr > line + trailcol && c == ' ')
|| (leadcol != 0 && ptr < line + leadcol && c == ' ')) {
c = (ptr > line + trailcol) ? wp->w_p_lcs_chars.trail
: wp->w_p_lcs_chars.lead;
n_attr = 1;
extra_attr = win_hl_attr(wp, HLF_0);
saved_attr2 = char_attr; // save current attr

View File

@ -110,6 +110,35 @@ func Test_listchars()
\ '.....h>-$',
\ 'iii<<<<><<$', '$'], l)
" Test lead and trail
normal ggdG
set listchars=eol:$
set listchars+=lead:>,trail:<,space:x
set list
call append(0, [
\ ' ffff ',
\ ' gg',
\ 'h ',
\ ' ',
\ ' 0 0 ',
\ ])
let expected = [
\ '>>>>ffff<<<<$',
\ '>>>>>>>>>>gg$',
\ 'h<<<<<<<<<<<$',
\ '<<<<<<<<<<<<$',
\ '>>>>0xx0<<<<$',
\ '$'
\ ]
redraw!
for i in range(1, 5)
call cursor(i, 1)
call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$')))
endfor
call assert_equal(expected, split(execute("%list"), "\n"))
" test nbsp
normal ggdG