Hello everyone,

I have been wanting this feature as well, so I made a patch.
The way it works is as follows:
   - an option, called "ntab" (for "new tab", or "end tab") is introduced 
within "listchars". It can be set like this: "ntab:1" or "ntab:y" or "ntab:Y" 
and unset with "ntab:0" or "ntab:n" or "ntab:N".
   - when "ntab" is off [default], things behave as they currently do
   - when "ntab" is on, the first character of "tab" is repeated, and the last 
character is mandatorily put.
This means that "tab:->,ntab:1" will show a tab that takes four spaces as 
"--->" and a tab that taks 1 space as ">".

I attach the patch with this e-mail.

Thanks!

Nathaniel


On Wednesday, January 2, 2013 5:50:23 PM UTC+1, Bram Moolenaar wrote:
> Andy Spencer wrote:
> 
> 
> 
> > On 2012-12-31 10:22, Kip Coul wrote:
> 
> > > Currently, the visualization of a tab is represented as a first
> 
> > > character followed by as many repetitions of a second character needed
> 
> > > to fill the width (lcs_tab1 and lcs_tab2 in the code, if I'm not
> 
> > > mistaken).
> 
> > > 
> 
> > > I'd like to do the opposite, through an option: the first character
> 
> > > repeated plus the second character at the end. That would enable using
> 
> > > arrows ('--->' for 4-space wide tabs).
> 
> > > 
> 
> > > What do you think about this? I could add an option such as 'tabview'
> 
> > > which could take two values.
> 
> > 
> 
> > I've wanted this before as well.
> 
> > 
> 
> > Maybe instead of adding another option you could modify how listchars
> 
> > works? You could use tab:xyz for the left character, the repeated middle
> 
> > character, and the (optional) right character. Then to get an arrow you
> 
> > could use:
> 
> >   
> 
> >   :set listchars=tab:-->
> 
> > 
> 
> > Any existing configurations that use the two character format `tab:xy'
> 
> > would just be a special case and would be equivalent to tab:xyy.
> 
> 
> 
> Instead of changing the meaning of tab: it's probably easier to add
> 
> another item, e.g. rtab:.  Or bat: (although most users will miss the
> 
> hint of a reverse tab...).
> 
> 
> 
> -- 
> 
> hundred-and-one symptoms of being an internet addict:
> 
> 227. You sleep next to your monitor.  Or on top of it.
> 
> 
> 
>  /// Bram Moolenaar -- XXXXXXXXXXX -- http://www.Moolenaar.net   \\\
> 
> ///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
> 
> \\\  an exciting new programming language -- http://www.Zimbu.org        ///
> 
>  \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
# HG changeset patch
# User Nathaniel Braun <pra...@gmail.com>
# Date 1381657097 -7200
# Node ID 9818b46545977cb1a260d5851cd5652a3d334af9
# Parent  92c9748e0ccbc42a5e28ce8fb9b8818e756a06da
Add "ntab" option to "listchars" for tab visualization

diff -r 92c9748e0ccb -r 9818b4654597 runtime/doc/options.txt
--- a/runtime/doc/options.txt	Sun Oct 06 17:46:56 2013 +0200
+++ b/runtime/doc/options.txt	Sun Oct 13 11:38:17 2013 +0200
@@ -4663,11 +4663,22 @@
 			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	Two characters to be used to show a tab.  One char is
+			used once, and the other is is repeated to fill the space
+			that the tab normally occupies, depending on "ntab".
+			If "ntab" is off, "tab:>-" will show a tab that takes
+			four spaces as ">---".  If "ntab" is on, "tab:->"
+			will show a tab that takes four spaces as "--->".
+			When omitted, a tab is shown as ^I.
+	  						*lcs-ntab*
+	  ntab:b	Boolean defining how a tab is displayed.
+			  - if "b" is set to '0', 'n' or 'N', "ntab" is off.
+			    The first char of "tab" is used once and the last
+			    char is repeated. [default]
+			  - if "b" is set to '1', 'y' or 'Y', "ntab" is on.
+			    The first char of "tab" is repeated and the last
+			    char is used once.
+			  - if "b" is anything else, an error is raised.
 	  						*lcs-trail*
 	  trail:c	Character to show for trailing spaces.  When omitted,
 			trailing spaces are blank.
diff -r 92c9748e0ccb -r 9818b4654597 runtime/doc/tags
--- a/runtime/doc/tags	Sun Oct 06 17:46:56 2013 +0200
+++ b/runtime/doc/tags	Sun Oct 13 11:38:17 2013 +0200
@@ -6647,6 +6647,7 @@
 lcs-eol	options.txt	/*lcs-eol*
 lcs-extends	options.txt	/*lcs-extends*
 lcs-nbsp	options.txt	/*lcs-nbsp*
+lcs-ntab	options.txt	/*lcs-ntab*
 lcs-precedes	options.txt	/*lcs-precedes*
 lcs-tab	options.txt	/*lcs-tab*
 lcs-trail	options.txt	/*lcs-trail*
diff -r 92c9748e0ccb -r 9818b4654597 src/globals.h
--- a/src/globals.h	Sun Oct 06 17:46:56 2013 +0200
+++ b/src/globals.h	Sun Oct 13 11:38:17 2013 +0200
@@ -1160,6 +1160,7 @@
 EXTERN int	lcs_nbsp INIT(= NUL);
 EXTERN int	lcs_tab1 INIT(= NUL);
 EXTERN int	lcs_tab2 INIT(= NUL);
+EXTERN int	lcs_ntab INIT(= FALSE);
 EXTERN int	lcs_trail INIT(= NUL);
 #ifdef FEAT_CONCEAL
 EXTERN int	lcs_conceal INIT(= '-');
diff -r 92c9748e0ccb -r 9818b4654597 src/message.c
--- a/src/message.c	Sun Oct 06 17:46:56 2013 +0200
+++ b/src/message.c	Sun Oct 13 11:38:17 2013 +0200
@@ -1646,6 +1646,7 @@
     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;
@@ -1676,7 +1677,9 @@
 	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++;
@@ -1712,11 +1715,13 @@
 		{
 		    c = ' ';
 		    c_extra = ' ';
+		    c_final = NUL;
 		}
 		else
 		{
-		    c = lcs_tab1;
-		    c_extra = lcs_tab2;
+		    c = (n_extra == 0 && lcs_ntab) ? lcs_tab2 : lcs_tab1;
+		    c_extra = lcs_ntab ? lcs_tab1 : lcs_tab2;
+		    c_final = lcs_ntab ? lcs_tab2 : NUL;
 		    attr = hl_attr(HLF_8);
 		}
 	    }
@@ -1729,6 +1734,7 @@
 	    {
 		p_extra = (char_u *)"";
 		c_extra = NUL;
+		c_final = NUL;
 		n_extra = 1;
 		c = lcs_eol;
 		attr = hl_attr(HLF_AT);
@@ -1739,6 +1745,7 @@
 		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 -r 92c9748e0ccb -r 9818b4654597 src/option.c
--- a/src/option.c	Sun Oct 06 17:46:56 2013 +0200
+++ b/src/option.c	Sun Oct 13 11:38:17 2013 +0200
@@ -7261,6 +7261,7 @@
 	{&lcs_nbsp,	"nbsp"},
 	{&lcs_prec,	"precedes"},
 	{&lcs_tab2,	"tab"},
+	{&lcs_ntab,	"ntab"},
 	{&lcs_trail,	"trail"},
 #ifdef FEAT_CONCEAL
 	{&lcs_conceal,	"conceal"},
@@ -7295,8 +7296,12 @@
 	    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_ntab = FALSE;
+	    }
 #if defined(FEAT_WINDOWS) || defined(FEAT_FOLDING)
 	    else
 		fill_diff = '-';
@@ -7332,6 +7337,16 @@
 			c2 = *s++;
 #endif
 		    }
+		    else if (tab[i].cp == &lcs_ntab)
+		    {
+			if(c1 == '1' || c1 == 'y' || c1 == 'Y')
+			    lcs_ntab = TRUE;
+			else if(c1 == '0' || c1 == 'n' || c1 == 'N')
+			    lcs_ntab = FALSE;
+			else
+			    continue;
+		    }
+
 		    if (*s == ',' || *s == NUL)
 		    {
 			if (round)
@@ -7341,6 +7356,8 @@
 				lcs_tab1 = c1;
 				lcs_tab2 = c2;
 			    }
+			    else if (tab[i].cp == &lcs_ntab)
+				lcs_ntab = (c1 == '1' || c1 == 'y' || c1 == 'Y') ? TRUE : FALSE;
 			    else if (tab[i].cp != NULL)
 				*(tab[i].cp) = c1;
 
diff -r 92c9748e0ccb -r 9818b4654597 src/screen.c
--- a/src/screen.c	Sun Oct 06 17:46:56 2013 +0200
+++ b/src/screen.c	Sun Oct 13 11:38:17 2013 +0200
@@ -2854,6 +2854,7 @@
     int		n_extra = 0;		/* number of extra chars */
     char_u	*p_extra = NULL;	/* string of extra chars, plus NUL */
     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 */
@@ -2864,6 +2865,7 @@
     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 */
@@ -3555,6 +3557,7 @@
 		    /* Draw the cmdline character. */
 		    n_extra = 1;
 		    c_extra = cmdwin_type;
+		    c_final = NUL;
 		    char_attr = hl_attr(HLF_AT);
 		}
 	    }
@@ -3572,6 +3575,7 @@
 		    p_extra = extra;
 		    p_extra[n_extra] = NUL;
 		    c_extra = NUL;
+		    c_final = NUL;
 		    char_attr = hl_attr(HLF_FC);
 		}
 	    }
@@ -3596,6 +3600,7 @@
 
 		    /* Draw two cells with the sign value or blank. */
 		    c_extra = ' ';
+		    c_final = NUL;
 		    char_attr = hl_attr(HLF_SC);
 		    n_extra = 2;
 
@@ -3610,9 +3615,13 @@
 			{
 			    /* 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;
 			}
@@ -3624,6 +3633,7 @@
 			    if (p_extra != NULL)
 			    {
 				c_extra = NUL;
+				c_final = NUL;
 				n_extra = (int)STRLEN(p_extra);
 			    }
 			    char_attr = sign_get_attr(text_sign, FALSE);
@@ -3681,9 +3691,13 @@
 #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
@@ -3707,9 +3721,15 @@
 		{
 		    /* 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;
@@ -3725,6 +3745,7 @@
 		    /* 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;
@@ -3750,6 +3771,7 @@
 		    /* 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;
 		}
@@ -3944,15 +3966,16 @@
 	 * 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 be mandatorily put 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)
-	    {
-		c = c_extra;
+	    if (c_extra != NUL || (n_extra == 1 && c_final != NUL))
+	    {
+		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 && (*mb_char2len)(c) > 1)
@@ -4103,6 +4126,7 @@
 			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;
@@ -4171,6 +4195,7 @@
 			    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)
 			    {
@@ -4211,6 +4236,7 @@
 		{
 		    n_extra = 1;
 		    c_extra = MB_FILLER_CHAR;
+		    c_final = NUL;
 		    c = ' ';
 		    if (area_attr == 0 && search_attr == 0)
 		    {
@@ -4411,6 +4437,7 @@
 # endif
 				1), (colnr_T)vcol, NULL) - 1;
 		    c_extra = ' ';
+		    c_final = NUL;
 		    if (vim_iswhite(c))
 		    {
 #ifdef FEAT_CONCEAL
@@ -4475,8 +4502,9 @@
 #endif
 		    if (wp->w_p_list)
 		    {
-			c = lcs_tab1;
-			c_extra = lcs_tab2;
+			c = (n_extra == 0 && lcs_ntab) ? lcs_tab2 : lcs_tab1;
+			c_extra = lcs_ntab ? lcs_tab1 : lcs_tab2;
+			c_final = lcs_ntab ? lcs_tab2 : NUL;
 			n_attr = n_extra + 1;
 			extra_attr = hl_attr(HLF_8);
 			saved_attr2 = char_attr; /* save current attr */
@@ -4492,6 +4520,7 @@
 		    }
 		    else
 		    {
+			c_final = NUL;
 			c_extra = ' ';
 			c = ' ';
 		    }
@@ -4543,6 +4572,7 @@
 			    p_extra = at_end_str;
 			    n_extra = 1;
 			    c_extra = NUL;
+			    c_final = NUL;
 			}
 		    }
 		    if (wp->w_p_list)
@@ -4577,6 +4607,7 @@
 #endif
 		    n_extra = byte2cells(c) - 1;
 		    c_extra = NUL;
+		    c_final = NUL;
 		    c = *p_extra++;
 		    if (!attr_pri)
 		    {
@@ -4791,6 +4822,7 @@
 		/* 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);
@@ -5447,6 +5479,7 @@
 	    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;

Raspunde prin e-mail lui