Skip to content

Commit f14b8ba

Browse files
zeertzjqbrammool
authored andcommitted
patch 8.2.3424: a sequence of spaces is hard to see in list mode
Problem: A sequence of spaces is hard to see in list mode. Solution: Add the "multispace" option to 'listchars'. (closes #8834)
1 parent 0780204 commit f14b8ba

File tree

7 files changed

+264
-29
lines changed

7 files changed

+264
-29
lines changed

runtime/doc/options.txt

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4939,16 +4939,25 @@ A jump table for the options with a short description can be found at |Q_op|.
49394939
*lcs-space*
49404940
space:c Character to show for a space. When omitted, spaces
49414941
are left blank.
4942+
*lcs-multispace*
4943+
multispace:c...
4944+
One or more characters to use cyclically to show for
4945+
multiple consecutive spaces. Overrides the "space"
4946+
setting, except for single spaces. When omitted, the
4947+
"space" setting is used. For example,
4948+
`:set listchars=multispace:---+` shows ten consecutive
4949+
spaces as:
4950+
---+---+--
49424951
*lcs-lead*
49434952
lead:c Character to show for leading spaces. When omitted,
4944-
leading spaces are blank. Overrides the "space"
4945-
setting for leading spaces. You can combine it with
4946-
"tab:", for example: >
4953+
leading spaces are blank. Overrides the "space" and
4954+
"multispace" settings for leading spaces. You can
4955+
combine it with "tab:", for example: >
49474956
:set listchars+=tab:>-,lead:.
49484957
< *lcs-trail*
49494958
trail:c Character to show for trailing spaces. When omitted,
4950-
trailing spaces are blank. Overrides the "space"
4951-
setting for trailing spaces.
4959+
trailing spaces are blank. Overrides the "space" and
4960+
"multispace" settings for trailing spaces.
49524961
*lcs-extends*
49534962
extends:c Character to show in the last column, when 'wrap' is
49544963
off and the line continues beyond the right of the

src/drawline.c

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,8 @@ win_line(
340340
#endif
341341
colnr_T trailcol = MAXCOL; // start of trailing spaces
342342
colnr_T leadcol = 0; // start of leading spaces
343+
int in_multispace = FALSE; // in multiple consecutive spaces
344+
int multispace_pos = 0; // position in lcs-multispace string
343345
#ifdef FEAT_LINEBREAK
344346
int need_showbreak = FALSE; // overlong line, skipping first x
345347
// chars
@@ -736,6 +738,7 @@ win_line(
736738
if (wp->w_p_list)
737739
{
738740
if (wp->w_lcs_chars.space
741+
|| wp->w_lcs_chars.multispace != NULL
739742
|| wp->w_lcs_chars.trail
740743
|| wp->w_lcs_chars.lead
741744
|| wp->w_lcs_chars.nbsp)
@@ -2011,6 +2014,11 @@ win_line(
20112014
}
20122015
#endif
20132016

2017+
in_multispace = c == ' '
2018+
&& ((ptr > line + 1 && ptr[-2] == ' ') || *ptr == ' ');
2019+
if (!in_multispace)
2020+
multispace_pos = 0;
2021+
20142022
// 'list': Change char 160 to 'nbsp' and space to 'space'
20152023
// setting in 'listchars'. But not when the character is
20162024
// followed by a composing character (use mb_l to check that).
@@ -2022,12 +2030,21 @@ win_line(
20222030
&& wp->w_lcs_chars.nbsp)
20232031
|| (c == ' '
20242032
&& mb_l == 1
2025-
&& wp->w_lcs_chars.space
2033+
&& (wp->w_lcs_chars.space
2034+
|| (in_multispace
2035+
&& wp->w_lcs_chars.multispace != NULL))
20262036
&& ptr - line >= leadcol
20272037
&& ptr - line <= trailcol)))
20282038
{
2029-
c = (c == ' ') ? wp->w_lcs_chars.space :
2030-
wp->w_lcs_chars.nbsp;
2039+
if (in_multispace && wp->w_lcs_chars.multispace != NULL)
2040+
{
2041+
c = wp->w_lcs_chars.multispace[multispace_pos++];
2042+
if (wp->w_lcs_chars.multispace[multispace_pos] == NUL)
2043+
multispace_pos = 0;
2044+
}
2045+
else
2046+
c = (c == ' ') ? wp->w_lcs_chars.space
2047+
: wp->w_lcs_chars.nbsp;
20312048
if (area_attr == 0 && search_attr == 0)
20322049
{
20332050
n_attr = 1;

src/message.c

Lines changed: 30 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,6 +1841,8 @@ msg_prt_line(char_u *s, int list)
18411841
int attr = 0;
18421842
char_u *trail = NULL;
18431843
char_u *lead = NULL;
1844+
int in_multispace = FALSE;
1845+
int multispace_pos = 0;
18441846
int l;
18451847
char_u buf[MB_MAXBYTES + 1];
18461848

@@ -1912,6 +1914,10 @@ msg_prt_line(char_u *s, int list)
19121914
{
19131915
attr = 0;
19141916
c = *s++;
1917+
in_multispace = c == ' '
1918+
&& ((col > 0 && s[-2] == ' ') || *s == ' ');
1919+
if (!in_multispace)
1920+
multispace_pos = 0;
19151921
if (c == TAB && (!list || curwin->w_lcs_chars.tab1))
19161922
{
19171923
// tab amount depends on current column
@@ -1963,20 +1969,31 @@ msg_prt_line(char_u *s, int list)
19631969
// the same in plain text.
19641970
attr = HL_ATTR(HLF_8);
19651971
}
1966-
else if (c == ' ' && lead != NULL && s <= lead)
1972+
else if (c == ' ')
19671973
{
1968-
c = curwin->w_lcs_chars.lead;
1969-
attr = HL_ATTR(HLF_8);
1970-
}
1971-
else if (c == ' ' && trail != NULL && s > trail)
1972-
{
1973-
c = curwin->w_lcs_chars.trail;
1974-
attr = HL_ATTR(HLF_8);
1975-
}
1976-
else if (c == ' ' && list && curwin->w_lcs_chars.space != NUL)
1977-
{
1978-
c = curwin->w_lcs_chars.space;
1979-
attr = HL_ATTR(HLF_8);
1974+
if (lead != NULL && s <= lead)
1975+
{
1976+
c = curwin->w_lcs_chars.lead;
1977+
attr = HL_ATTR(HLF_8);
1978+
}
1979+
else if (trail != NULL && s > trail)
1980+
{
1981+
c = curwin->w_lcs_chars.trail;
1982+
attr = HL_ATTR(HLF_8);
1983+
}
1984+
else if (list && in_multispace
1985+
&& curwin->w_lcs_chars.multispace != NULL)
1986+
{
1987+
c = curwin->w_lcs_chars.multispace[multispace_pos++];
1988+
if (curwin->w_lcs_chars.multispace[multispace_pos] == NUL)
1989+
multispace_pos = 0;
1990+
attr = HL_ATTR(HLF_8);
1991+
}
1992+
else if (list && curwin->w_lcs_chars.space != NUL)
1993+
{
1994+
c = curwin->w_lcs_chars.space;
1995+
attr = HL_ATTR(HLF_8);
1996+
}
19801997
}
19811998
}
19821999

src/screen.c

Lines changed: 58 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4787,6 +4787,8 @@ set_chars_option(win_T *wp, char_u **varp)
47874787
int round, i, len, entries;
47884788
char_u *p, *s;
47894789
int c1 = 0, c2 = 0, c3 = 0;
4790+
char_u *last_multispace; // Last occurrence of "multispace:"
4791+
int multispace_len = 0; // Length of lcs-multispace string
47904792
struct charstab
47914793
{
47924794
int *cp;
@@ -4853,6 +4855,13 @@ set_chars_option(win_T *wp, char_u **varp)
48534855
{
48544856
lcs_chars.tab1 = NUL;
48554857
lcs_chars.tab3 = NUL;
4858+
if (multispace_len)
4859+
{
4860+
lcs_chars.multispace = ALLOC_MULT(int, multispace_len + 1);
4861+
lcs_chars.multispace[multispace_len] = NUL;
4862+
}
4863+
else
4864+
lcs_chars.multispace = NULL;
48564865
}
48574866
else
48584867
{
@@ -4877,19 +4886,19 @@ set_chars_option(win_T *wp, char_u **varp)
48774886
s = p + len + 1;
48784887
c1 = mb_ptr2char_adv(&s);
48794888
if (mb_char2cells(c1) > 1)
4880-
continue;
4889+
return e_invarg;
48814890
if (tab[i].cp == &lcs_chars.tab2)
48824891
{
48834892
if (*s == NUL)
4884-
continue;
4893+
return e_invarg;
48854894
c2 = mb_ptr2char_adv(&s);
48864895
if (mb_char2cells(c2) > 1)
4887-
continue;
4896+
return e_invarg;
48884897
if (!(*s == ',' || *s == NUL))
48894898
{
48904899
c3 = mb_ptr2char_adv(&s);
48914900
if (mb_char2cells(c3) > 1)
4892-
continue;
4901+
return e_invarg;
48934902
}
48944903
}
48954904

@@ -4914,13 +4923,57 @@ set_chars_option(win_T *wp, char_u **varp)
49144923
}
49154924

49164925
if (i == entries)
4917-
return e_invarg;
4926+
{
4927+
len = STRLEN("multispace");
4928+
if ((varp == &p_lcs || varp == &wp->w_p_lcs)
4929+
&& STRNCMP(p, "multispace", len) == 0
4930+
&& p[len] == ':'
4931+
&& p[len + 1] != NUL)
4932+
{
4933+
s = p + len + 1;
4934+
if (round == 0)
4935+
{
4936+
// Get length of lcs-multispace string in first round
4937+
last_multispace = p;
4938+
multispace_len = 0;
4939+
while (*s != NUL && *s != ',')
4940+
{
4941+
c1 = mb_ptr2char_adv(&s);
4942+
if (mb_char2cells(c1) > 1)
4943+
return e_invarg;
4944+
++multispace_len;
4945+
}
4946+
if (multispace_len == 0)
4947+
// lcs-multispace cannot be an empty string
4948+
return e_invarg;
4949+
p = s;
4950+
}
4951+
else
4952+
{
4953+
int multispace_pos = 0;
4954+
while (*s != NUL && *s != ',')
4955+
{
4956+
c1 = mb_ptr2char_adv(&s);
4957+
if (p == last_multispace)
4958+
lcs_chars.multispace[multispace_pos++] = c1;
4959+
}
4960+
p = s;
4961+
}
4962+
}
4963+
else
4964+
return e_invarg;
4965+
}
4966+
49184967
if (*p == ',')
49194968
++p;
49204969
}
49214970
}
49224971
if (tab == lcstab)
4972+
{
4973+
if (wp->w_lcs_chars.multispace != NULL)
4974+
vim_free(wp->w_lcs_chars.multispace);
49234975
wp->w_lcs_chars = lcs_chars;
4976+
}
49244977

49254978
return NULL; // no error
49264979
}

src/structs.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3376,6 +3376,7 @@ typedef struct
33763376
int tab3;
33773377
int trail;
33783378
int lead;
3379+
int *multispace;
33793380
#ifdef FEAT_CONCEAL
33803381
int conceal;
33813382
#endif

0 commit comments

Comments
 (0)