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
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* *lcs-space*
space:c Character to show for a space. When omitted, spaces space:c Character to show for a space. When omitted, spaces
are left blank. 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* *lcs-trail*
trail:c Character to show for trailing spaces. When omitted, trail:c Character to show for trailing spaces. When omitted,
trailing spaces are blank. Overrides the "space" trailing spaces are blank. Overrides the "space"

View File

@@ -1201,6 +1201,7 @@ struct window_S {
int tab1; ///< first tab character int tab1; ///< first tab character
int tab2; ///< second tab character int tab2; ///< second tab character
int tab3; ///< third tab character int tab3; ///< third tab character
int lead;
int trail; int trail;
int conceal; int conceal;
} w_p_lcs_chars; } 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 char_u *p_extra = NULL; // init to make SASC shut up
int n; int n;
int attr = 0; int attr = 0;
char_u *lead = NULL;
char_u *trail = NULL; char_u *trail = NULL;
int l; int l;
@@ -1712,11 +1713,24 @@ void msg_prt_line(char_u *s, int list)
list = true; list = true;
} }
// find start of trailing whitespace if (list) {
if (list && curwin->w_p_lcs_chars.trail) { // find start of trailing whitespace
trail = s + STRLEN(s); if (curwin->w_p_lcs_chars.trail) {
while (trail > s && ascii_iswhite(trail[-1])) { trail = s + STRLEN(s);
trail--; 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 /* Use special coloring to be able to distinguish <hex> from
* the same in plain text. */ * the same in plain text. */
attr = HL_ATTR(HLF_8); 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) { } else if (c == ' ' && trail != NULL && s > trail) {
c = curwin->w_p_lcs_chars.trail; c = curwin->w_p_lcs_chars.trail;
attr = HL_ATTR(HLF_8); 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.prec, "precedes", NUL },
{ &wp->w_p_lcs_chars.space, "space", NUL }, { &wp->w_p_lcs_chars.space, "space", NUL },
{ &wp->w_p_lcs_chars.tab2, "tab", 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.trail, "trail", NUL },
{ &wp->w_p_lcs_chars.conceal, "conceal", 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_start = MAXCOL; // first col of changed area
int change_end = -1; // last col of changed area int change_end = -1; // last col of changed area
colnr_T trailcol = MAXCOL; // start of trailing spaces 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 bool need_showbreak = false; // overlong line, skip first x chars
int line_attr = 0; // attribute for the whole line int line_attr = 0; // attribute for the whole line
int line_attr_lowprio = 0; // low-priority attribute for the 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_list && !has_fold) {
if (wp->w_p_lcs_chars.space if (wp->w_p_lcs_chars.space
|| wp->w_p_lcs_chars.trail || wp->w_p_lcs_chars.trail
|| wp->w_p_lcs_chars.lead
|| wp->w_p_lcs_chars.nbsp) { || wp->w_p_lcs_chars.nbsp) {
extra_check = true; 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); 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))) || (mb_utf8 && (mb_c == 160 || mb_c == 0x202f)))
&& curwin->w_p_lcs_chars.nbsp) && curwin->w_p_lcs_chars.nbsp)
|| (c == ' ' && curwin->w_p_lcs_chars.space || (c == ' ' && curwin->w_p_lcs_chars.space
&& ptr - line >= leadcol
&& ptr - line <= trailcol))) { && ptr - line <= trailcol))) {
c = (c == ' ') ? wp->w_p_lcs_chars.space : wp->w_p_lcs_chars.nbsp; c = (c == ' ') ? wp->w_p_lcs_chars.space : wp->w_p_lcs_chars.nbsp;
n_attr = 1; 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 == ' ') { if ((trailcol != MAXCOL && ptr > line + trailcol && c == ' ')
c = wp->w_p_lcs_chars.trail; || (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; n_attr = 1;
extra_attr = win_hl_attr(wp, HLF_0); extra_attr = win_hl_attr(wp, HLF_0);
saved_attr2 = char_attr; // save current attr saved_attr2 = char_attr; // save current attr

View File

@@ -110,6 +110,35 @@ func Test_listchars()
\ '.....h>-$', \ '.....h>-$',
\ 'iii<<<<><<$', '$'], l) \ '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 " test nbsp
normal ggdG normal ggdG