summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2019-01-16 22:41:54 +0100
committerBram Moolenaar <Bram@vim.org>2019-01-16 22:41:54 +0100
commit83a52171ba00b2b9fd2d1d22a07e38fc9fc69c1e (patch)
tree5b8e1eaf85ad03ccaa27aec30fff6775bef44d71
parent500f36108031c75befb6a04cac2ceeb592d8cf00 (diff)
downloadvim-git-83a52171ba00b2b9fd2d1d22a07e38fc9fc69c1e.tar.gz
patch 8.1.0759: showing two characters for tab is limitedv8.1.0759
Problem: Showing two characters for tab is limited. Solution: Allow for a third character for "tab:" in 'listchars'. (Nathaniel Braun, Ken Takata, closes #3810)
-rw-r--r--runtime/doc/options.txt25
-rw-r--r--src/globals.h1
-rw-r--r--src/message.c11
-rw-r--r--src/option.c19
-rw-r--r--src/screen.c39
-rw-r--r--src/testdir/test_listchars.vim32
-rw-r--r--src/version.c2
7 files changed, 118 insertions, 11 deletions
diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt
index 008926f63..be53e9f56 100644
--- a/runtime/doc/options.txt
+++ b/runtime/doc/options.txt
@@ -5063,11 +5063,26 @@ A jump table for the options with a short description can be found at |Q_op|.
omitted, there is no extra character at the end of the
line.
*lcs-tab*
- tab:xy Two characters to be used to show a tab. The first
- char is used once. The second char is repeated to
- fill the space that the tab normally occupies.
- "tab:>-" will show a tab that takes four spaces as
- ">---". When omitted, a tab is show as ^I.
+ tab:xy[z] Two or three characters to be used to show a tab.
+ The third character is optional.
+
+ tab:xy The 'x' is always used, then 'y' as many times as will
+ fit. Thus "tab:>-" displays:
+ >
+ >-
+ >--
+ etc.
+
+ tab:xyz The 'z' is always used, then 'x' is prepended, and
+ then 'y' is used as many times as will fit. Thus
+ "tab:<->" displays:
+ >
+ <>
+ <->
+ <-->
+ etc.
+
+ When "tab:" is omitted, a tab is shown as ^I.
*lcs-space*
space:c Character to show for a space. When omitted, spaces
are left blank.
diff --git a/src/globals.h b/src/globals.h
index 27b1562e8..4a0c52ce4 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -1163,6 +1163,7 @@ EXTERN int lcs_nbsp INIT(= NUL);
EXTERN int lcs_space INIT(= NUL);
EXTERN int lcs_tab1 INIT(= NUL);
EXTERN int lcs_tab2 INIT(= NUL);
+EXTERN int lcs_tab3 INIT(= NUL);
EXTERN int lcs_trail INIT(= NUL);
#ifdef FEAT_CONCEAL
EXTERN int lcs_conceal INIT(= ' ');
diff --git a/src/message.c b/src/message.c
index 635dd8be9..9969632dd 100644
--- a/src/message.c
+++ b/src/message.c
@@ -1771,6 +1771,7 @@ msg_prt_line(char_u *s, int list)
int col = 0;
int n_extra = 0;
int c_extra = 0;
+ int c_final = 0;
char_u *p_extra = NULL; /* init to make SASC shut up */
int n;
int attr = 0;
@@ -1801,7 +1802,9 @@ msg_prt_line(char_u *s, int list)
if (n_extra > 0)
{
--n_extra;
- if (c_extra)
+ if (n_extra == 0 && c_final)
+ c = c_final;
+ else if (c_extra)
c = c_extra;
else
c = *p_extra++;
@@ -1844,11 +1847,13 @@ msg_prt_line(char_u *s, int list)
{
c = ' ';
c_extra = ' ';
+ c_final = NUL;
}
else
{
- c = lcs_tab1;
+ c = (n_extra == 0 && lcs_tab3) ? lcs_tab3 : lcs_tab1;
c_extra = lcs_tab2;
+ c_final = lcs_tab3;
attr = HL_ATTR(HLF_8);
}
}
@@ -1861,6 +1866,7 @@ msg_prt_line(char_u *s, int list)
{
p_extra = (char_u *)"";
c_extra = NUL;
+ c_final = NUL;
n_extra = 1;
c = lcs_eol;
attr = HL_ATTR(HLF_AT);
@@ -1871,6 +1877,7 @@ msg_prt_line(char_u *s, int list)
n_extra = n - 1;
p_extra = transchar_byte(c);
c_extra = NUL;
+ c_final = NUL;
c = *p_extra++;
/* Use special coloring to be able to distinguish <hex> from
* the same in plain text. */
diff --git a/src/option.c b/src/option.c
index ca3e3d830..ec058e97d 100644
--- a/src/option.c
+++ b/src/option.c
@@ -7949,7 +7949,7 @@ set_chars_option(char_u **varp)
{
int round, i, len, entries;
char_u *p, *s;
- int c1, c2 = 0;
+ int c1 = 0, c2 = 0, c3 = 0;
struct charstab
{
int *cp;
@@ -8001,8 +8001,12 @@ set_chars_option(char_u **varp)
for (i = 0; i < entries; ++i)
if (tab[i].cp != NULL)
*(tab[i].cp) = (varp == &p_lcs ? NUL : ' ');
+
if (varp == &p_lcs)
+ {
lcs_tab1 = NUL;
+ lcs_tab3 = NUL;
+ }
else
fill_diff = '-';
}
@@ -8016,6 +8020,7 @@ set_chars_option(char_u **varp)
&& p[len] == ':'
&& p[len + 1] != NUL)
{
+ c1 = c2 = c3 = 0;
s = p + len + 1;
#ifdef FEAT_MBYTE
c1 = mb_ptr2char_adv(&s);
@@ -8035,7 +8040,18 @@ set_chars_option(char_u **varp)
#else
c2 = *s++;
#endif
+ if (!(*s == ',' || *s == NUL))
+ {
+#ifdef FEAT_MBYTE
+ c3 = mb_ptr2char_adv(&s);
+ if (mb_char2cells(c3) > 1)
+ continue;
+#else
+ c3 = *s++;
+#endif
+ }
}
+
if (*s == ',' || *s == NUL)
{
if (round)
@@ -8044,6 +8060,7 @@ set_chars_option(char_u **varp)
{
lcs_tab1 = c1;
lcs_tab2 = c2;
+ lcs_tab3 = c3;
}
else if (tab[i].cp != NULL)
*(tab[i].cp) = c1;
diff --git a/src/screen.c b/src/screen.c
index 9b976ffaf..cd146fd6c 100644
--- a/src/screen.c
+++ b/src/screen.c
@@ -3049,6 +3049,7 @@ win_line(
char_u *p_extra = NULL; /* string of extra chars, plus NUL */
char_u *p_extra_free = NULL; /* p_extra needs to be freed */
int c_extra = NUL; /* extra chars, all the same */
+ int c_final = NUL; /* final char, mandatory if set */
int extra_attr = 0; /* attributes when n_extra != 0 */
static char_u *at_end_str = (char_u *)""; /* used for p_extra when
displaying lcs_eol at end-of-line */
@@ -3059,6 +3060,7 @@ win_line(
int saved_n_extra = 0;
char_u *saved_p_extra = NULL;
int saved_c_extra = 0;
+ int saved_c_final = 0;
int saved_char_attr = 0;
int n_attr = 0; /* chars with special attr */
@@ -3814,6 +3816,7 @@ win_line(
/* Draw the cmdline character. */
n_extra = 1;
c_extra = cmdwin_type;
+ c_final = NUL;
char_attr = HL_ATTR(HLF_AT);
}
}
@@ -3839,6 +3842,7 @@ win_line(
p_extra_free[n_extra] = NUL;
p_extra = p_extra_free;
c_extra = NUL;
+ c_final = NUL;
char_attr = HL_ATTR(HLF_FC);
}
}
@@ -3860,6 +3864,7 @@ win_line(
/* Draw two cells with the sign value or blank. */
c_extra = ' ';
+ c_final = NUL;
char_attr = HL_ATTR(HLF_SC);
n_extra = 2;
@@ -3878,9 +3883,13 @@ win_line(
{
/* Use the image in this position. */
c_extra = SIGN_BYTE;
+ c_final = NUL;
# ifdef FEAT_NETBEANS_INTG
if (buf_signcount(wp->w_buffer, lnum) > 1)
+ {
c_extra = MULTISIGN_BYTE;
+ c_final = NUL;
+ }
# endif
char_attr = icon_sign;
}
@@ -3892,6 +3901,7 @@ win_line(
if (p_extra != NULL)
{
c_extra = NUL;
+ c_final = NUL;
n_extra = (int)STRLEN(p_extra);
}
char_attr = sign_get_attr(text_sign, FALSE);
@@ -3949,9 +3959,13 @@ win_line(
#endif
p_extra = extra;
c_extra = NUL;
+ c_final = NUL;
}
else
+ {
c_extra = ' ';
+ c_final = NUL;
+ }
n_extra = number_width(wp) + 1;
char_attr = HL_ATTR(HLF_N);
#ifdef FEAT_SYN_HL
@@ -4020,9 +4034,15 @@ win_line(
{
/* Draw "deleted" diff line(s). */
if (char2cells(fill_diff) > 1)
+ {
c_extra = '-';
+ c_final = NUL;
+ }
else
+ {
c_extra = fill_diff;
+ c_final = NUL;
+ }
# ifdef FEAT_RIGHTLEFT
if (wp->w_p_rl)
n_extra = col + 1;
@@ -4038,6 +4058,7 @@ win_line(
/* Draw 'showbreak' at the start of each broken line. */
p_extra = p_sbr;
c_extra = NUL;
+ c_final = NUL;
n_extra = (int)STRLEN(p_sbr);
char_attr = HL_ATTR(HLF_AT);
need_showbreak = FALSE;
@@ -4065,6 +4086,7 @@ win_line(
/* Continue item from end of wrapped line. */
n_extra = saved_n_extra;
c_extra = saved_c_extra;
+ c_final = saved_c_final;
p_extra = saved_p_extra;
char_attr = saved_char_attr;
}
@@ -4364,15 +4386,16 @@ win_line(
* The "p_extra" points to the extra stuff that is inserted to
* represent special characters (non-printable stuff) and other
* things. When all characters are the same, c_extra is used.
+ * If c_final is set, it will compulsorily be used at the end.
* "p_extra" must end in a NUL to avoid mb_ptr2len() reads past
* "p_extra[n_extra]".
* For the '$' of the 'list' option, n_extra == 1, p_extra == "".
*/
if (n_extra > 0)
{
- if (c_extra != NUL)
+ if (c_extra != NUL || (n_extra == 1 && c_final != NUL))
{
- c = c_extra;
+ c = (n_extra == 1 && c_final != NUL) ? c_final : c_extra;
#ifdef FEAT_MBYTE
mb_c = c; /* doesn't handle non-utf-8 multi-byte! */
if (enc_utf8 && utf_char2len(c) > 1)
@@ -4537,6 +4560,7 @@ win_line(
mb_utf8 = (c >= 0x80);
n_extra = (int)STRLEN(p_extra);
c_extra = NUL;
+ c_final = NUL;
if (area_attr == 0 && search_attr == 0)
{
n_attr = n_extra + 1;
@@ -4605,6 +4629,7 @@ win_line(
p_extra = extra;
n_extra = (int)STRLEN(extra) - 1;
c_extra = NUL;
+ c_final = NUL;
c = *p_extra++;
if (area_attr == 0 && search_attr == 0)
{
@@ -4645,6 +4670,7 @@ win_line(
{
n_extra = 1;
c_extra = MB_FILLER_CHAR;
+ c_final = NUL;
c = ' ';
if (area_attr == 0 && search_attr == 0)
{
@@ -4856,6 +4882,7 @@ win_line(
# else
c_extra = ' ';
# endif
+ c_final = NUL;
if (VIM_ISWHITE(c))
{
#ifdef FEAT_CONCEAL
@@ -5040,13 +5067,14 @@ win_line(
#endif
if (wp->w_p_list)
{
- c = lcs_tab1;
+ c = (n_extra == 0 && lcs_tab3) ? lcs_tab3 : lcs_tab1;
#ifdef FEAT_LINEBREAK
if (wp->w_p_lbr)
c_extra = NUL; /* using p_extra from above */
else
#endif
c_extra = lcs_tab2;
+ c_final = lcs_tab3;
n_attr = tab_len + 1;
extra_attr = HL_ATTR(HLF_8);
saved_attr2 = char_attr; /* save current attr */
@@ -5062,6 +5090,7 @@ win_line(
}
else
{
+ c_final = NUL;
c_extra = ' ';
c = ' ';
}
@@ -5111,6 +5140,7 @@ win_line(
p_extra = at_end_str;
n_extra = 1;
c_extra = NUL;
+ c_final = NUL;
}
}
if (wp->w_p_list && lcs_eol > 0)
@@ -5146,6 +5176,7 @@ win_line(
rl_mirror(p_extra); /* reverse "<12>" */
#endif
c_extra = NUL;
+ c_final = NUL;
#ifdef FEAT_LINEBREAK
if (wp->w_p_lbr)
{
@@ -5407,6 +5438,7 @@ win_line(
/* Double-width character being overwritten by the "precedes"
* character, need to fill up half the character. */
c_extra = MB_FILLER_CHAR;
+ c_final = NUL;
n_extra = 1;
n_attr = 2;
extra_attr = HL_ATTR(HLF_AT);
@@ -6064,6 +6096,7 @@ win_line(
saved_n_extra = n_extra;
saved_p_extra = p_extra;
saved_c_extra = c_extra;
+ saved_c_final = c_final;
saved_char_attr = char_attr;
n_extra = 0;
lcs_prec_todo = lcs_prec;
diff --git a/src/testdir/test_listchars.vim b/src/testdir/test_listchars.vim
index 57ea7ca5a..4899f5991 100644
--- a/src/testdir/test_listchars.vim
+++ b/src/testdir/test_listchars.vim
@@ -42,6 +42,38 @@ func Test_listchars()
call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$')))
endfor
+ " tab with 3rd character.
+ set listchars-=tab:>-
+ set listchars+=tab:<=>,trail:-
+ let expected = [
+ \ '<======>aa<====>$',
+ \ '..bb<==>--$',
+ \ '...cccc>-$',
+ \ 'dd........ee--<>$',
+ \ '-$'
+ \ ]
+ redraw!
+ for i in range(1, 5)
+ call cursor(i, 1)
+ call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$')))
+ endfor
+
+ set listchars-=trail:-
+ let expected = [
+ \ '<======>aa<====>$',
+ \ '..bb<==>..$',
+ \ '...cccc>.$',
+ \ 'dd........ee..<>$',
+ \ '.$'
+ \ ]
+ redraw!
+ for i in range(1, 5)
+ call cursor(i, 1)
+ call assert_equal([expected[i - 1]], ScreenLines(i, virtcol('$')))
+ endfor
+
+ set listchars-=tab:<=>
+ set listchars+=tab:>-
set listchars+=trail:<
set nolist
normal ggdG
diff --git a/src/version.c b/src/version.c
index 710c0245e..c4c596956 100644
--- a/src/version.c
+++ b/src/version.c
@@ -796,6 +796,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 759,
+/**/
758,
/**/
757,