> 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;
> }
>
>