The `no-tab-mode' minor mode is currently hidden behind some #ifdef, and I'd like to enable it since it's really useful. It's the equivalent of vi' `expandtab', i.e. makes the TAB key inserting spaces up to the next tab stop.
My plan would be to follow-up with a diff to make the tab width customizable per-buffer (vi' `shiftwidth'): together, these two settings could allow mg to be used for a variety of situations with very little effort. When re-enabling the no-tab-mode I've initially just un-ifdef'd NOTAB, but the result is not correct IMHO: even under no-tab-mode mg should consider a literal TAB character wide until the next tab stop, so in a few places I've not preserved the un-ifdef'd check. I've also introduced an helper function doindent() in utils.c to simplify the task of inserting tabs/spaces until the given column. ok? diff /usr/src commit - 4bc3741a05f858113bfe387089085a77ab225ec5 path + /usr/src blob - 4a170480432e59db5d6b39096587ffef3a2310e6 file + usr.bin/mg/basic.c --- usr.bin/mg/basic.c +++ usr.bin/mg/basic.c @@ -274,14 +274,9 @@ getgoal(struct line *dlp) int c, i, col = 0; char tmp[5]; - for (i = 0; i < llength(dlp); i++) { c = lgetc(dlp, i); - if (c == '\t' -#ifdef NOTAB - && !(curbp->b_flag & BFNOTAB) -#endif - ) { + if (c == '\t') { col |= 0x07; col++; } else if (ISCTRL(c) != FALSE) { blob - 9f5ffd72f80efd74432dafaa3e48b72acc7b932f file + usr.bin/mg/cmode.c --- usr.bin/mg/cmode.c +++ usr.bin/mg/cmode.c @@ -245,11 +245,7 @@ getindent(const struct line *lp, int *curi) for (lo = 0; lo < llength(lp); lo++) { if (!isspace(c = lgetc(lp, lo))) break; - if (c == '\t' -#ifdef NOTAB - && !(curbp->b_flag & BFNOTAB) -#endif /* NOTAB */ - ) { + if (c == '\t') { nicol |= 0x07; } nicol++; @@ -414,11 +410,7 @@ findcolpos(const struct buffer *bp, const struct line for (i = 0; i < lo; ++i) { c = lgetc(lp, i); - if (c == '\t' -#ifdef NOTAB - && !(bp->b_flag & BFNOTAB) -#endif /* NOTAB */ - ) { + if (c == '\t') { col |= 0x07; col++; } else if (ISCTRL(c) != FALSE) blob - 5475b513036334b5bfd5530cf100291c218cddce file + usr.bin/mg/def.h --- usr.bin/mg/def.h +++ usr.bin/mg/def.h @@ -285,9 +285,7 @@ struct buffer { #define BFCHG 0x01 /* Changed. */ #define BFBAK 0x02 /* Need to make a backup. */ -#ifdef NOTAB #define BFNOTAB 0x04 /* no tab mode */ -#endif #define BFOVERWRITE 0x08 /* overwrite mode */ #define BFREADONLY 0x10 /* read only mode */ #define BFDIRTY 0x20 /* Buffer was modified elsewhere */ @@ -676,9 +674,7 @@ int fillmode(int, int); /* modes.c X */ int indentmode(int, int); int fillmode(int, int); -#ifdef NOTAB int notabmode(int, int); -#endif /* NOTAB */ int overwrite_mode(int, int); int set_default_mode(int,int); blob - 1751b5ead137bde915e470e79fe5a9ec6b91b29e file + usr.bin/mg/display.c --- usr.bin/mg/display.c +++ usr.bin/mg/display.c @@ -317,11 +317,7 @@ vtputc(int c) vp = vscreen[vtrow]; if (vtcol >= ncol) vp->v_text[ncol - 1] = '$'; - else if (c == '\t' -#ifdef NOTAB - && !(curbp->b_flag & BFNOTAB) -#endif - ) { + else if (c == '\t') { do { vtputc(' '); } while (vtcol < ncol && (vtcol & 0x07) != 0); @@ -353,11 +349,7 @@ vtpute(int c) vp = vscreen[vtrow]; if (vtcol >= ncol) vp->v_text[ncol - 1] = '$'; - else if (c == '\t' -#ifdef NOTAB - && !(curbp->b_flag & BFNOTAB) -#endif - ) { + else if (c == '\t') { do { vtpute(' '); } while (((vtcol + lbound) & 0x07) != 0 && vtcol < ncol); @@ -516,11 +508,7 @@ update(int modelinecolor) i = 0; while (i < curwp->w_doto) { c = lgetc(lp, i++); - if (c == '\t' -#ifdef NOTAB - && !(curbp->b_flag & BFNOTAB) -#endif - ) { + if (c == '\t') { curcol |= 0x07; curcol++; } else if (ISCTRL(c) != FALSE) blob - e1c59fa0fb43a02c6233288b57d1a6332c5b6282 file + usr.bin/mg/funmap.c --- usr.bin/mg/funmap.c +++ usr.bin/mg/funmap.c @@ -157,9 +157,7 @@ static struct funmap functnames[] = { {enewline, "newline", 1}, {lfindent, "newline-and-indent", 1}, {forwline, "next-line", 1}, -#ifdef NOTAB {notabmode, "no-tab-mode", 0}, -#endif /* NOTAB */ {notmodified, "not-modified", 0}, {openline, "open-line", 1}, {nextwind, "other-window", 0}, @@ -212,9 +210,7 @@ static struct funmap functnames[] = { {shellcommand, "shell-command", 1}, {piperegion, "shell-command-on-region", 1}, {shrinkwind, "shrink-window", 1}, -#ifdef NOTAB {space_to_tabstop, "space-to-tabstop", 0}, -#endif /* NOTAB */ {splitwind, "split-window-vertically", 0}, {definemacro, "start-kbd-macro", 0}, {spawncli, "suspend-emacs", 0}, blob - 6e47e4f66cb257bb0d6ef6dce565ec955cdb9f96 file + usr.bin/mg/keymap.c --- usr.bin/mg/keymap.c +++ usr.bin/mg/keymap.c @@ -464,7 +464,6 @@ static struct KEYMAPE (1) indntmap = { } }; -#ifdef NOTAB static PF notab_tab[] = { space_to_tabstop /* ^I */ }; @@ -479,7 +478,6 @@ static struct KEYMAPE (1) notabmap = { } } }; -#endif /* NOTAB */ static struct KEYMAPE (1) overwmap = { 0, @@ -511,9 +509,7 @@ static struct maps_s map_table[] = { static struct maps_s map_table[] = { {(KEYMAP *) &fillmap, "fill",}, {(KEYMAP *) &indntmap, "indent",}, -#ifdef NOTAB {(KEYMAP *) ¬abmap, "notab",}, -#endif /* NOTAB */ {(KEYMAP *) &overwmap, "overwrite",}, {(KEYMAP *) &metamap, "esc prefix",}, {(KEYMAP *) &cXmap, "c-x prefix",}, blob - d35fcfdb66e738e11a7b780888f620cdd30ad718 file + usr.bin/mg/match.c --- usr.bin/mg/match.c +++ usr.bin/mg/match.c @@ -169,11 +169,7 @@ displaymatch(struct line *clp, int cbo) bufo = 0; for (cp = 0; cp < llength(clp); cp++) { c = lgetc(clp, cp); - if (c != '\t' -#ifdef NOTAB - || (curbp->b_flag & BFNOTAB) -#endif - ) + if (c != '\t') if (ISCTRL(c)) { buf[bufo++] = '^'; buf[bufo++] = CCHR(c); blob - beb85f1151fff5e340bf12efbe98e7d810b66f86 file + usr.bin/mg/mg.1 --- usr.bin/mg/mg.1 +++ usr.bin/mg/mg.1 @@ -738,9 +738,9 @@ lines. Move forward .Va n lines. -.\" .It no-tab-mode -.\" Toggle notab mode. -.\" In this mode, spaces are inserted rather than tabs. +.It no-tab-mode +Toggle notab mode. +In this mode, spaces are inserted rather than tabs. .It not-modified Turn off the modified flag in the current buffer. .It open-line blob - 9d5e4ce5373d8f5f315ee1a47a6461d0d51b5200 file + usr.bin/mg/modes.c --- usr.bin/mg/modes.c +++ usr.bin/mg/modes.c @@ -78,7 +78,6 @@ fillmode(int f, int n) return (changemode(f, n, "fill")); } -#ifdef NOTAB int notabmode(int f, int n) { @@ -93,7 +92,6 @@ notabmode(int f, int n) curbp->b_flag ^= BFNOTAB; return (TRUE); } -#endif /* NOTAB */ int overwrite_mode(int f, int n) @@ -162,13 +160,11 @@ set_default_mode(int f, int n) else defb_flag |= BFOVERWRITE; } -#ifdef NOTAB if (strcmp(modebuf, "notab") == 0) { if (n <= 0) defb_flag &= ~BFNOTAB; else defb_flag |= BFNOTAB; } -#endif /* NOTAB */ return (TRUE); } blob - b49a488a04155cde477c05387920907dad14ba1d file + usr.bin/mg/paragraph.c --- usr.bin/mg/paragraph.c +++ usr.bin/mg/paragraph.c @@ -412,11 +412,7 @@ fillword(int f, int n) if (i == curwp->w_doto) return selfinsert(f, n); c = lgetc(curwp->w_dotp, i); - if (c == '\t' -#ifdef NOTAB - && !(curbp->b_flag & BFNOTAB) -#endif - ) + if (c == '\t') col |= 0x07; else if (ISCTRL(c) != FALSE) ++col; blob - 5899b8a29b086226689a879a996682988bb42aa0 file + usr.bin/mg/util.c --- usr.bin/mg/util.c +++ usr.bin/mg/util.c @@ -100,11 +100,7 @@ getcolpos(struct mgwin *wp) for (i = 0; i < wp->w_doto; ++i) { c = lgetc(wp->w_dotp, i); - if (c == '\t' -#ifdef NOTAB - && !(wp->w_bufp->b_flag & BFNOTAB) -#endif /* NOTAB */ - ) { + if (c == '\t') { col |= 0x07; col++; } else if (ISCTRL(c) != FALSE) @@ -336,7 +332,23 @@ deltrailwhite(int f, int n) return (TRUE); } +/* + * Raw indent routine. Use spaces and tabs to fill the given number of + * cols, but respect no-tab-mode. + */ +int +doindent(int cols) +{ + int n; + if (curbp->b_flag & BFNOTAB) + return (linsert(cols, ' ')); + if ((n = cols / 8) != 0 && linsert(n, '\t') == FALSE) + return (FALSE); + if ((n = cols % 8) != 0 && linsert(n, ' ') == FALSE) + return (FALSE); + return (TRUE); +} /* * Insert a newline, then enough tabs and spaces to duplicate the indentation @@ -367,12 +379,8 @@ lfindent(int f, int n) ++nicol; } (void)delwhite(FFRAND, 1); - if (lnewline() == FALSE || (( -#ifdef NOTAB - curbp->b_flag & BFNOTAB) ? linsert(nicol, ' ') == FALSE : ( -#endif /* NOTAB */ - ((i = nicol / 8) != 0 && linsert(i, '\t') == FALSE) || - ((i = nicol % 8) != 0 && linsert(i, ' ') == FALSE)))) { + + if (lnewline() == FALSE || doindent(nicol) == FALSE) { s = FALSE; break; } @@ -389,7 +397,7 @@ indent(int f, int n) int indent(int f, int n) { - int soff, i; + int soff; if (n < 0) return (FALSE); @@ -403,12 +411,7 @@ indent(int f, int n) /* insert appropriate whitespace */ soff = curwp->w_doto; (void)gotobol(FFRAND, 1); - if ( -#ifdef NOTAB - (curbp->b_flag & BFNOTAB) ? linsert(n, ' ') == FALSE : -#endif /* NOTAB */ - (((i = n / 8) != 0 && linsert(i, '\t') == FALSE) || - ((i = n % 8) != 0 && linsert(i, ' ') == FALSE))) + if (doindent(n) == FALSE) return (FALSE); forwchar(FFRAND, soff); @@ -464,7 +467,6 @@ backdel(int f, int n) return (s); } -#ifdef NOTAB int space_to_tabstop(int f, int n) { @@ -474,7 +476,6 @@ space_to_tabstop(int f, int n) return (TRUE); return (linsert((n << 3) - (curwp->w_doto & 7), ' ')); } -#endif /* NOTAB */ /* * Move the dot to the first non-whitespace character of the current line.