> On 28 Apr 2020, at 13:31, Todd C. Miller <mill...@openbsd.org> wrote:
> 
> On Thu, 02 Apr 2020 16:21:47 -0600, "Todd C. Miller" wrote:
> 
>> In vim, the expandtab option expands tabs to spaces in insert mode
>> as well as when shifting and indenting/outdenting.  This is very
>> useful when working on a code-base where the style dictates using
>> spaces instead of tabs for indentation.
>> 
>> NetBSD added an implementation of expandtab to their vi some time
>> ago, but theirs doesn't convert tabs to spaces in insert mode.  I've
>> adapted the NetBSD patch and added support for expanding tabs in
>> insert mode, unless escaped via ^V.
>> 
>> The option is off by default (of course).
>> 
>> Comments?  Please, no tabs vs spaces flame wars.
> 
> Ping?  It would be nice for this to make 6.7.

im ok with it.

i've only read it, but it makes sense. i mostly like the idea that i wouldn't 
have to to use (or install) another editor if i need this.

dlg

> 
> - todd
> 
> Index: usr.bin/vi/common/options.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/vi/common/options.c,v
> retrieving revision 1.27
> diff -u -p -u -r1.27 options.c
> --- usr.bin/vi/common/options.c       21 May 2019 09:24:58 -0000      1.27
> +++ usr.bin/vi/common/options.c       2 Apr 2020 20:43:14 -0000
> @@ -69,6 +69,8 @@ OPTLIST const optlist[] = {
>       {"escapetime",  NULL,           OPT_NUM,        0},
> /* O_ERRORBELLS           4BSD */
>       {"errorbells",  NULL,           OPT_0BOOL,      0},
> +/* O_EXPANDTAB           NetBSD 5.0 */
> +     {"expandtab",   NULL,           OPT_0BOOL,      0},
> /* O_EXRC     System V (undocumented) */
>       {"exrc",        NULL,           OPT_0BOOL,      0},
> /* O_EXTENDED   4.4BSD */
> @@ -207,6 +209,7 @@ static OABBREV const abbrev[] = {
>       {"co",          O_COLUMNS},             /*   4.4BSD */
>       {"eb",          O_ERRORBELLS},          /*     4BSD */
>       {"ed",          O_EDCOMPATIBLE},        /*     4BSD */
> +     {"et",          O_EXPANDTAB},           /* NetBSD 5.0 */
>       {"ex",          O_EXRC},                /* System V (undocumented) */
>       {"ht",          O_HARDTABS},            /*     4BSD */
>       {"ic",          O_IGNORECASE},          /*     4BSD */
> Index: usr.bin/vi/docs/USD.doc/vi.man/vi.1
> ===================================================================
> RCS file: /cvs/src/usr.bin/vi/docs/USD.doc/vi.man/vi.1,v
> retrieving revision 1.77
> diff -u -p -u -r1.77 vi.1
> --- usr.bin/vi/docs/USD.doc/vi.man/vi.1       4 Oct 2019 20:12:01 -0000       
> 1.77
> +++ usr.bin/vi/docs/USD.doc/vi.man/vi.1       2 Apr 2020 22:05:31 -0000
> @@ -1606,6 +1606,11 @@ and
> characters to move forward to the next
> .Ar shiftwidth
> column boundary.
> +If the
> +.Cm expandtab
> +option is set, only insert
> +.Aq space
> +characters.
> .Pp
> .It Aq Cm erase
> .It Aq Cm control-H
> @@ -2343,6 +2348,16 @@ key mapping.
> .Nm ex
> only.
> Announce error messages with a bell.
> +.It Cm expandtab , et Bq off
> +Expand
> +.Aq tab
> +characters to
> +.Aq space
> +when inserting, replacing or shifting text, autoindenting,
> +indenting with
> +.Aq Ic control-T ,
> +or outdenting with
> +.Aq Ic control-D .
> .It Cm exrc , ex Bq off
> Read the startup files in the local directory.
> .It Cm extended Bq off
> Index: usr.bin/vi/docs/USD.doc/vi.ref/set.opt.roff
> ===================================================================
> RCS file: /cvs/src/usr.bin/vi/docs/USD.doc/vi.ref/set.opt.roff,v
> retrieving revision 1.12
> diff -u -p -u -r1.12 set.opt.roff
> --- usr.bin/vi/docs/USD.doc/vi.ref/set.opt.roff       8 Aug 2016 15:09:33 
> -0000       1.12
> +++ usr.bin/vi/docs/USD.doc/vi.ref/set.opt.roff       2 Apr 2020 22:05:27 
> -0000
> @@ -96,7 +96,9 @@ the first nonblank character of the line
> Lines are indented using tab characters to the extent possible (based on
> the value of the
> .OP tabstop
> -option) and then using space characters as necessary.
> +option, and if
> +.OP expandtab
> +is not set) and then using space characters as necessary.
> For commands inserting text into the middle of a line, any blank characters
> to the right of the cursor are discarded, and the first nonblank character
> to the right of the cursor is aligned as described above.
> @@ -400,6 +402,17 @@ only.
> error messages are normally presented in inverse video.
> If that is not possible for the terminal, setting this option causes
> error messages to be announced by ringing the terminal bell.
> +.KY expandtab
> +.IP "expandtab, et [off]"
> +Expand
> +.LI <tab>
> +characters to
> +.LI <space>
> +when inserting, replacing or shifting text, autoindenting,
> +indenting with
> +.CO <control-T>,
> +or outdenting with
> +.CO <control-D>.
> .KY exrc
> .IP "exrc, ex [off]"
> If this option is turned on in the EXINIT environment variables,
> Index: usr.bin/vi/ex/ex_shift.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/vi/ex/ex_shift.c,v
> retrieving revision 1.8
> diff -u -p -u -r1.8 ex_shift.c
> --- usr.bin/vi/ex/ex_shift.c  6 Jan 2016 22:28:52 -0000       1.8
> +++ usr.bin/vi/ex/ex_shift.c  2 Apr 2020 20:53:16 -0000
> @@ -127,10 +127,13 @@ shift(SCR *sp, EXCMD *cmdp, enum which r
>                * Build a new indent string and count the number of
>                * characters it uses.
>                */
> -             for (tbp = bp, newidx = 0;
> -                 newcol >= O_VAL(sp, O_TABSTOP); ++newidx) {
> -                     *tbp++ = '\t';
> -                     newcol -= O_VAL(sp, O_TABSTOP);
> +             tbp = bp;
> +             newidx = 0;
> +             if (!O_ISSET(sp, O_EXPANDTAB)) {
> +                     for (; newcol >= O_VAL(sp, O_TABSTOP); ++newidx) {
> +                             *tbp++ = '\t';
> +                             newcol -= O_VAL(sp, O_TABSTOP);
> +                     }
>               }
>               for (; newcol > 0; --newcol, ++newidx)
>                       *tbp++ = ' ';
> Index: usr.bin/vi/ex/ex_txt.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/vi/ex/ex_txt.c,v
> retrieving revision 1.16
> diff -u -p -u -r1.16 ex_txt.c
> --- usr.bin/vi/ex/ex_txt.c    27 May 2016 09:18:12 -0000      1.16
> +++ usr.bin/vi/ex/ex_txt.c    2 Apr 2020 20:53:58 -0000
> @@ -400,8 +400,12 @@ txt_dent(SCR *sp, TEXT *tp)
>        *
>        * Count up spaces/tabs needed to get to the target.
>        */
> -     for (cno = 0, tabs = 0; cno + COL_OFF(cno, ts) <= scno; ++tabs)
> -             cno += COL_OFF(cno, ts);
> +     cno = 0;
> +     tabs = 0;
> +     if (!O_ISSET(sp, O_EXPANDTAB)) {
> +             for (; cno + COL_OFF(cno, ts) <= scno; ++tabs)
> +                     cno += COL_OFF(cno, ts);
> +     }
>       spaces = scno - cno;
> 
>       /* Make sure there's enough room. */
> Index: usr.bin/vi/vi/v_txt.c
> ===================================================================
> RCS file: /cvs/src/usr.bin/vi/vi/v_txt.c,v
> retrieving revision 1.33
> diff -u -p -u -r1.33 v_txt.c
> --- usr.bin/vi/vi/v_txt.c     27 May 2016 09:18:12 -0000      1.33
> +++ usr.bin/vi/vi/v_txt.c     2 Apr 2020 22:13:09 -0000
> @@ -32,7 +32,7 @@
> static int     txt_abbrev(SCR *, TEXT *, CHAR_T *, int, int *, int *);
> static void    txt_ai_resolve(SCR *, TEXT *, int *);
> static TEXT   *txt_backup(SCR *, TEXTH *, TEXT *, u_int32_t *);
> -static int    txt_dent(SCR *, TEXT *, int);
> +static int    txt_dent(SCR *, TEXT *, int, int);
> static int     txt_emark(SCR *, TEXT *, size_t);
> static void    txt_err(SCR *, TEXTH *);
> static int     txt_fc(SCR *, TEXT *, int *);
> @@ -968,7 +968,7 @@ leftmargin:               tp->lb[tp->cno - 1] = ' ';
>                       if (tp->ai == 0 || tp->cno > tp->ai + tp->offset)
>                               goto ins_ch;
> 
> -                     (void)txt_dent(sp, tp, 0);
> +                     (void)txt_dent(sp, tp, O_SHIFTWIDTH, 0);
>                       break;
>               default:
>                       abort();
> @@ -1184,7 +1184,7 @@ leftmargin:             tp->lb[tp->cno - 1] = ' ';
>       case K_CNTRLT:                  /* Add autoindent characters. */
>               if (!LF_ISSET(TXT_CNTRLT))
>                       goto ins_ch;
> -             if (txt_dent(sp, tp, 1))
> +             if (txt_dent(sp, tp, O_SHIFTWIDTH, 1))
>                       goto err;
>               goto ebuf_chk;
>       case K_RIGHTBRACE:
> @@ -1213,6 +1213,13 @@ leftmargin:            tp->lb[tp->cno - 1] = ' ';
>       case K_HEXCHAR:
>               hexcnt = 1;
>               goto insq_ch;
> +     case K_TAB:
> +             if (quote != Q_VTHIS && O_ISSET(sp, O_EXPANDTAB)) {
> +                     if (txt_dent(sp, tp, O_TABSTOP, 1))
> +                             goto err;
> +                     goto ebuf_chk;
> +             }
> +             goto insq_ch;
>       default:                        /* Insert the character. */
> ins_ch:               /*
>                * Historically, vi eliminated nul's out of hand.  If the
> @@ -1683,13 +1690,19 @@ txt_ai_resolve(SCR *sp, TEXT *tp, int *c
>       /*
>        * If there are no spaces, or no tabs after spaces and less than
>        * ts spaces, it's already minimal.
> +      * Keep analysing if expandtab is set.
>        */
> -     if (!spaces || (!tab_after_sp && spaces < ts))
> +     if ((!spaces || (!tab_after_sp && spaces < ts)) &&
> +         !O_ISSET(sp, O_EXPANDTAB))
>               return;
> 
>       /* Count up spaces/tabs needed to get to the target. */
> -     for (cno = 0, tabs = 0; cno + COL_OFF(cno, ts) <= scno; ++tabs)
> -             cno += COL_OFF(cno, ts);
> +     cno = 0;
> +     tabs = 0;
> +     if (!O_ISSET(sp, O_EXPANDTAB)) {
> +             for (; cno + COL_OFF(cno, ts) <= scno; ++tabs)
> +                     cno += COL_OFF(cno, ts);
> +     }
>       spaces = scno - cno;
> 
>       /*
> @@ -1846,7 +1859,7 @@ txt_backup(SCR *sp, TEXTH *tiqh, TEXT *t
>  * changes.
>  */
> static int
> -txt_dent(SCR *sp, TEXT *tp, int isindent)
> +txt_dent(SCR *sp, TEXT *tp, int swopt, int isindent)
> {
>       CHAR_T ch;
>       u_long sw, ts;
> @@ -1854,7 +1867,7 @@ txt_dent(SCR *sp, TEXT *tp, int isindent
>       int ai_reset;
> 
>       ts = O_VAL(sp, O_TABSTOP);
> -     sw = O_VAL(sp, O_SHIFTWIDTH);
> +     sw = O_VAL(sp, swopt);
> 
>       /*
>        * Since we don't know what precedes the character(s) being inserted
> @@ -1921,9 +1934,12 @@ txt_dent(SCR *sp, TEXT *tp, int isindent
>       if (current >= target)
>               spaces = tabs = 0;
>       else {
> -             for (cno = current,
> -                 tabs = 0; cno + COL_OFF(cno, ts) <= target; ++tabs)
> -                     cno += COL_OFF(cno, ts);
> +             cno = current;
> +             tabs = 0;
> +             if (!O_ISSET(sp, O_EXPANDTAB)) {
> +                     for (; cno + COL_OFF(cno, ts) <= target; ++tabs)
> +                             cno += COL_OFF(cno, ts);
> +                     }
>               spaces = target - cno;
>       }
> 
> 

Reply via email to