summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOmar Polo <op@cvs.openbsd.org>2023-04-21 13:39:38 +0000
committerOmar Polo <op@cvs.openbsd.org>2023-04-21 13:39:38 +0000
commit442f0aa59a4408f16c76cc8c40f8fc16f6ee4b66 (patch)
tree6bfa7ee6462267f901724bff43b220a0383c3438
parent902bea4ec8059a9e73832d155f8bce0a9b9139a0 (diff)
mg: allow to change the tab width
This makes the tab width customizable per-buffer. The new function `set-tab-width' changes it for the current buffer or the default value for new buffers if called with a prefix argument (or from the startup file.) The default tab width is still 8 column. Together with the newly resurrected no-tab-mode, allows to use mg for a variety of programming languages and coding styles. Note that it's not possible to call set-tab-width with auto-execute in the startup file due to limitations in how auto-execute and the parser work. ok tb@
-rw-r--r--usr.bin/mg/basic.c5
-rw-r--r--usr.bin/mg/buffer.c36
-rw-r--r--usr.bin/mg/cmode.c13
-rw-r--r--usr.bin/mg/def.h5
-rw-r--r--usr.bin/mg/display.c93
-rw-r--r--usr.bin/mg/funmap.c3
-rw-r--r--usr.bin/mg/match.c7
-rw-r--r--usr.bin/mg/mg.17
-rw-r--r--usr.bin/mg/paragraph.c4
-rw-r--r--usr.bin/mg/util.c28
10 files changed, 130 insertions, 71 deletions
diff --git a/usr.bin/mg/basic.c b/usr.bin/mg/basic.c
index ed7d475c494..d5f8ecb1796 100644
--- a/usr.bin/mg/basic.c
+++ b/usr.bin/mg/basic.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: basic.c,v 1.53 2023/04/17 09:49:04 op Exp $ */
+/* $OpenBSD: basic.c,v 1.54 2023/04/21 13:39:36 op Exp $ */
/* This file is in the public domain */
@@ -277,8 +277,7 @@ getgoal(struct line *dlp)
for (i = 0; i < llength(dlp); i++) {
c = lgetc(dlp, i);
if (c == '\t') {
- col |= 0x07;
- col++;
+ col = ntabstop(col, curbp->b_tabw);
} else if (ISCTRL(c) != FALSE) {
col += 2;
} else if (isprint(c))
diff --git a/usr.bin/mg/buffer.c b/usr.bin/mg/buffer.c
index e6605000475..8c8aab40a86 100644
--- a/usr.bin/mg/buffer.c
+++ b/usr.bin/mg/buffer.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: buffer.c,v 1.113 2023/03/08 04:43:11 guenther Exp $ */
+/* $OpenBSD: buffer.c,v 1.114 2023/04/21 13:39:36 op Exp $ */
/* This file is in the public domain. */
@@ -26,9 +26,42 @@ static struct buffer *bnew(const char *);
static int usebufname(const char *);
+/* Default tab width */
+int defb_tabw = 8;
+
/* Flag for global working dir */
extern int globalwd;
+/*
+ * Set the tab width for the current buffer, or the default for new
+ * buffers if called with a prefix argument.
+ */
+int
+settabw(int f, int n)
+{
+ char buf[8], *bufp;
+ const char *errstr;
+
+ if (f & FFARG) {
+ if (n <= 0 || n > 16)
+ return (FALSE);
+ defb_tabw = n;
+ return (TRUE);
+ }
+
+ if ((bufp = eread("Tab Width: ", buf, sizeof(buf),
+ EFNUL | EFNEW | EFCR)) == NULL)
+ return (ABORT);
+ if (bufp[0] == '\0')
+ return (ABORT);
+ n = strtonum(buf, 1, 16, &errstr);
+ if (errstr)
+ return (dobeep_msgs("Tab width", errstr));
+ curbp->b_tabw = n;
+ curwp->w_rflag |= WFFRAME;
+ return (TRUE);
+}
+
int
togglereadonlyall(int f, int n)
{
@@ -588,6 +621,7 @@ bnew(const char *bname)
bp->b_lines = 1;
bp->b_nlseq = "\n"; /* use unix default */
bp->b_nlchr = bp->b_nlseq;
+ bp->b_tabw = defb_tabw;
if ((bp->b_bname = strdup(bname)) == NULL) {
dobeep();
ewprintf("Can't get %d bytes", strlen(bname) + 1);
diff --git a/usr.bin/mg/cmode.c b/usr.bin/mg/cmode.c
index e5442a2b6ed..2a2a1090003 100644
--- a/usr.bin/mg/cmode.c
+++ b/usr.bin/mg/cmode.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cmode.c,v 1.21 2023/04/17 09:49:04 op Exp $ */
+/* $OpenBSD: cmode.c,v 1.22 2023/04/21 13:39:37 op Exp $ */
/*
* This file is in the public domain.
*
@@ -245,10 +245,10 @@ getindent(const struct line *lp, int *curi)
for (lo = 0; lo < llength(lp); lo++) {
if (!isspace(c = lgetc(lp, lo)))
break;
- if (c == '\t') {
- nicol |= 0x07;
- }
- nicol++;
+ if (c == '\t')
+ nicol = ntabstop(nicol, curbp->b_tabw);
+ else
+ nicol++;
}
/* If last line was blank, choose 0 */
@@ -411,8 +411,7 @@ findcolpos(const struct buffer *bp, const struct line *lp, int lo)
for (i = 0; i < lo; ++i) {
c = lgetc(lp, i);
if (c == '\t') {
- col |= 0x07;
- col++;
+ col = ntabstop(col, curbp->b_tabw);
} else if (ISCTRL(c) != FALSE)
col += 2;
else if (isprint(c)) {
diff --git a/usr.bin/mg/def.h b/usr.bin/mg/def.h
index 8cfaada0300..65ae2b43c06 100644
--- a/usr.bin/mg/def.h
+++ b/usr.bin/mg/def.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: def.h,v 1.179 2023/04/17 09:49:04 op Exp $ */
+/* $OpenBSD: def.h,v 1.180 2023/04/21 13:39:37 op Exp $ */
/* This file is in the public domain. */
@@ -269,6 +269,7 @@ struct buffer {
char b_cwd[NFILEN]; /* working directory */
char *b_nlseq; /* Newline sequence of chars */
char *b_nlchr; /* 1st newline character */
+ int b_tabw; /* Width of a tab character */
struct fileinfo b_fi; /* File attributes */
struct undoq b_undo; /* Undo actions list */
struct undo_rec *b_undoptr;
@@ -430,6 +431,7 @@ int shrinkwind(int, int);
int delwind(int, int);
/* buffer.c */
+int settabw(int, int);
int togglereadonly(int, int);
int togglereadonlyall(int, int);
struct buffer *bfind(const char *, int);
@@ -542,6 +544,7 @@ int gotoline(int, int);
int setlineno(int);
/* util.c X */
+int ntabstop(int, int);
int showcpos(int, int);
int getcolpos(struct mgwin *);
int twiddle(int, int);
diff --git a/usr.bin/mg/display.c b/usr.bin/mg/display.c
index 3814a0bd29b..ab923d4fb9d 100644
--- a/usr.bin/mg/display.c
+++ b/usr.bin/mg/display.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: display.c,v 1.51 2023/04/17 09:49:04 op Exp $ */
+/* $OpenBSD: display.c,v 1.52 2023/04/21 13:39:37 op Exp $ */
/* This file is in the public domain. */
@@ -52,9 +52,9 @@ struct score {
};
void vtmove(int, int);
-void vtputc(int);
-void vtpute(int);
-int vtputs(const char *);
+void vtputc(int, struct mgwin *);
+void vtpute(int, struct mgwin *);
+int vtputs(const char *, struct mgwin *);
void vteeol(void);
void updext(int, int);
void modeline(struct mgwin *, int);
@@ -308,9 +308,10 @@ vtmove(int row, int col)
* Three guesses how we found this.
*/
void
-vtputc(int c)
+vtputc(int c, struct mgwin *wp)
{
struct video *vp;
+ int target;
c &= 0xff;
@@ -318,19 +319,20 @@ vtputc(int c)
if (vtcol >= ncol)
vp->v_text[ncol - 1] = '$';
else if (c == '\t') {
+ target = ntabstop(vtcol, wp->w_bufp->b_tabw);
do {
- vtputc(' ');
- } while (vtcol < ncol && (vtcol & 0x07) != 0);
+ vtputc(' ', wp);
+ } while (vtcol < ncol && vtcol < target);
} else if (ISCTRL(c)) {
- vtputc('^');
- vtputc(CCHR(c));
+ vtputc('^', wp);
+ vtputc(CCHR(c), wp);
} else if (isprint(c))
vp->v_text[vtcol++] = c;
else {
char bf[5];
snprintf(bf, sizeof(bf), "\\%o", c);
- vtputs(bf);
+ vtputs(bf, wp);
}
}
@@ -340,9 +342,10 @@ vtputc(int c)
* margin.
*/
void
-vtpute(int c)
+vtpute(int c, struct mgwin *wp)
{
struct video *vp;
+ int target;
c &= 0xff;
@@ -350,12 +353,13 @@ vtpute(int c)
if (vtcol >= ncol)
vp->v_text[ncol - 1] = '$';
else if (c == '\t') {
+ target = ntabstop(vtcol + lbound, wp->w_bufp->b_tabw);
do {
- vtpute(' ');
- } while (((vtcol + lbound) & 0x07) != 0 && vtcol < ncol);
+ vtpute(' ', wp);
+ } while (((vtcol + lbound) < target) && vtcol < ncol);
} else if (ISCTRL(c) != FALSE) {
- vtpute('^');
- vtpute(CCHR(c));
+ vtpute('^', wp);
+ vtpute(CCHR(c), wp);
} else if (isprint(c)) {
if (vtcol >= 0)
vp->v_text[vtcol] = c;
@@ -365,7 +369,7 @@ vtpute(int c)
snprintf(bf, sizeof(bf), "\\%o", c);
for (cp = bf; *cp != '\0'; cp++)
- vtpute(*cp);
+ vtpute(*cp, wp);
}
}
@@ -476,7 +480,7 @@ update(int modelinecolor)
vscreen[i]->v_flag |= (VFCHG | VFHBAD);
vtmove(i, 0);
for (j = 0; j < llength(lp); ++j)
- vtputc(lgetc(lp, j));
+ vtputc(lgetc(lp, j), wp);
vteeol();
} else if ((wp->w_rflag & (WFEDIT | WFFULL)) != 0) {
hflag = TRUE;
@@ -486,7 +490,7 @@ update(int modelinecolor)
vtmove(i, 0);
if (lp != wp->w_bufp->b_headp) {
for (j = 0; j < llength(lp); ++j)
- vtputc(lgetc(lp, j));
+ vtputc(lgetc(lp, j), wp);
lp = lforw(lp);
}
vteeol();
@@ -509,8 +513,7 @@ update(int modelinecolor)
while (i < curwp->w_doto) {
c = lgetc(lp, i++);
if (c == '\t') {
- curcol |= 0x07;
- curcol++;
+ curcol = ntabstop(curcol, curwp->w_bufp->b_tabw);
} else if (ISCTRL(c) != FALSE)
curcol += 2;
else if (isprint(c))
@@ -545,7 +548,7 @@ update(int modelinecolor)
(curcol < ncol - 1)) {
vtmove(i, 0);
for (j = 0; j < llength(lp); ++j)
- vtputc(lgetc(lp, j));
+ vtputc(lgetc(lp, j), wp);
vteeol();
/* this line no longer is extended */
vscreen[i]->v_flag &= ~VFEXT;
@@ -677,7 +680,7 @@ updext(int currow, int curcol)
vtmove(currow, -lbound); /* start scanning offscreen */
lp = curwp->w_dotp; /* line to output */
for (j = 0; j < llength(lp); ++j) /* until the end-of-line */
- vtpute(lgetc(lp, j));
+ vtpute(lgetc(lp, j), curwp);
vteeol(); /* truncate the virtual line */
vscreen[currow]->v_text[0] = '$'; /* and put a '$' in column 1 */
}
@@ -793,45 +796,45 @@ modeline(struct mgwin *wp, int modelinecolor)
vscreen[n]->v_flag |= (VFCHG | VFHBAD); /* Recompute, display. */
vtmove(n, 0); /* Seek to right line. */
bp = wp->w_bufp;
- vtputc('-');
- vtputc('-');
+ vtputc('-', wp);
+ vtputc('-', wp);
if ((bp->b_flag & BFREADONLY) != 0) {
- vtputc('%');
+ vtputc('%', wp);
if ((bp->b_flag & BFCHG) != 0)
- vtputc('*');
+ vtputc('*', wp);
else
- vtputc('%');
+ vtputc('%', wp);
} else if ((bp->b_flag & BFCHG) != 0) { /* "*" if changed. */
- vtputc('*');
- vtputc('*');
+ vtputc('*', wp);
+ vtputc('*', wp);
} else {
- vtputc('-');
- vtputc('-');
+ vtputc('-', wp);
+ vtputc('-', wp);
}
- vtputc('-');
+ vtputc('-', wp);
n = 5;
- n += vtputs("Mg: ");
+ n += vtputs("Mg: ", wp);
if (bp->b_bname[0] != '\0')
- n += vtputs(&(bp->b_bname[0]));
+ n += vtputs(&(bp->b_bname[0]), wp);
while (n < 42) { /* Pad out with blanks. */
- vtputc(' ');
+ vtputc(' ', wp);
++n;
}
- vtputc('(');
+ vtputc('(', wp);
++n;
for (md = 0; ; ) {
- n += vtputs(bp->b_modes[md]->p_name);
+ n += vtputs(bp->b_modes[md]->p_name, wp);
if (++md > bp->b_nmodes)
break;
- vtputc('-');
+ vtputc('-', wp);
++n;
}
/* XXX These should eventually move to a real mode */
if (macrodef == TRUE)
- n += vtputs("-def");
+ n += vtputs("-def", wp);
if (globalwd == TRUE)
- n += vtputs("-gwd");
- vtputc(')');
+ n += vtputs("-gwd", wp);
+ vtputc(')', wp);
++n;
if (linenos && colnos)
@@ -842,10 +845,10 @@ modeline(struct mgwin *wp, int modelinecolor)
else if (colnos)
len = snprintf(sl, sizeof(sl), "--C%d", getcolpos(wp));
if ((linenos || colnos) && len < sizeof(sl) && len != -1)
- n += vtputs(sl);
+ n += vtputs(sl, wp);
while (n < ncol) { /* Pad out. */
- vtputc('-');
+ vtputc('-', wp);
++n;
}
}
@@ -854,12 +857,12 @@ modeline(struct mgwin *wp, int modelinecolor)
* Output a string to the mode line, report how long it was.
*/
int
-vtputs(const char *s)
+vtputs(const char *s, struct mgwin *wp)
{
int n = 0;
while (*s != '\0') {
- vtputc(*s++);
+ vtputc(*s++, wp);
++n;
}
return (n);
diff --git a/usr.bin/mg/funmap.c b/usr.bin/mg/funmap.c
index fbf41217328..ae1c455edff 100644
--- a/usr.bin/mg/funmap.c
+++ b/usr.bin/mg/funmap.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: funmap.c,v 1.66 2023/04/17 09:49:04 op Exp $ */
+/* $OpenBSD: funmap.c,v 1.67 2023/04/21 13:39:37 op Exp $ */
/* This file is in the public domain */
@@ -199,6 +199,7 @@ static struct funmap functnames[] = {
{ask_selfinsert, "self-insert-char", 1},
{selfinsert, "self-insert-command", 1}, /* startup only */
{sentencespace, "sentence-end-double-space", 0},
+ {settabw, "set-tab-width", 1},
#ifdef REGEX
{setcasefold, "set-case-fold-search", 0},
#endif /* REGEX */
diff --git a/usr.bin/mg/match.c b/usr.bin/mg/match.c
index acb814e3b9d..9481985ee57 100644
--- a/usr.bin/mg/match.c
+++ b/usr.bin/mg/match.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: match.c,v 1.24 2023/04/17 15:18:25 op Exp $ */
+/* $OpenBSD: match.c,v 1.25 2023/04/21 13:39:37 op Exp $ */
/* This file is in the public domain. */
@@ -136,6 +136,7 @@ displaymatch(struct line *clp, int cbo)
int cp;
int bufo;
int c;
+ int col;
int inwindow;
char buf[NLINE];
@@ -181,9 +182,9 @@ displaymatch(struct line *clp, int cbo)
} else
buf[bufo++] = c;
} else {
- do {
+ col = ntabstop(bufo, curbp->b_tabw);
+ while (bufo < col && bufo < sizeof(buf) - 1)
buf[bufo++] = ' ';
- } while ((bufo & 7) && bufo < sizeof(buf) - 1);
}
}
buf[bufo++] = '\0';
diff --git a/usr.bin/mg/mg.1 b/usr.bin/mg/mg.1
index d2edd289cc5..0b677e9c4ca 100644
--- a/usr.bin/mg/mg.1
+++ b/usr.bin/mg/mg.1
@@ -1,7 +1,7 @@
-.\" $OpenBSD: mg.1,v 1.129 2023/04/17 09:49:04 op Exp $
+.\" $OpenBSD: mg.1,v 1.130 2023/04/21 13:39:37 op Exp $
.\" This file is in the public domain.
.\"
-.Dd $Mdocdate: April 17 2023 $
+.Dd $Mdocdate: April 21 2023 $
.Dt MG 1
.Os
.Sh NAME
@@ -896,6 +896,9 @@ Used by auto-fill-mode.
Sets the mark in the current window to the current dot location.
.It set-prefix-string
Sets the prefix string to be used by the 'prefix-region' command.
+.It set-tab-width
+Set the tab width for the current buffer, or the default for new buffers
+if called with a prefix argument or from the startup file.
.It shell-command
Execute external command from mini-buffer.
.It shell-command-on-region
diff --git a/usr.bin/mg/paragraph.c b/usr.bin/mg/paragraph.c
index 1455295f90d..4e35770e65f 100644
--- a/usr.bin/mg/paragraph.c
+++ b/usr.bin/mg/paragraph.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: paragraph.c,v 1.48 2023/04/17 09:49:04 op Exp $ */
+/* $OpenBSD: paragraph.c,v 1.49 2023/04/21 13:39:37 op Exp $ */
/* This file is in the public domain. */
@@ -413,7 +413,7 @@ fillword(int f, int n)
return selfinsert(f, n);
c = lgetc(curwp->w_dotp, i);
if (c == '\t')
- col |= 0x07;
+ col = ntabstop(col, curwp->w_bufp->b_tabw);
else if (ISCTRL(c) != FALSE)
++col;
}
diff --git a/usr.bin/mg/util.c b/usr.bin/mg/util.c
index 05fd84f91c8..6168f51144b 100644
--- a/usr.bin/mg/util.c
+++ b/usr.bin/mg/util.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: util.c,v 1.47 2023/04/17 09:53:08 op Exp $ */
+/* $OpenBSD: util.c,v 1.48 2023/04/21 13:39:37 op Exp $ */
/* This file is in the public domain. */
@@ -19,6 +19,16 @@
int doindent(int);
/*
+ * Compute next tab stop, with `col' being the a column number and
+ * `tabw' the tab width.
+ */
+int
+ntabstop(int col, int tabw)
+{
+ return (((col + tabw) / tabw) * tabw);
+}
+
+/*
* Display a bunch of useful information about the current location of dot.
* The character under the cursor (in octal), the current line, row, and
* column, and approximate position of the cursor in the file (as a
@@ -103,8 +113,7 @@ getcolpos(struct mgwin *wp)
for (i = 0; i < wp->w_doto; ++i) {
c = lgetc(wp->w_dotp, i);
if (c == '\t') {
- col |= 0x07;
- col++;
+ col = ntabstop(col, wp->w_bufp->b_tabw);
} else if (ISCTRL(c) != FALSE)
col += 2;
else if (isprint(c)) {
@@ -377,8 +386,9 @@ lfindent(int f, int n)
if (c != ' ' && c != '\t')
break;
if (c == '\t')
- nicol |= 0x07;
- ++nicol;
+ nicol = ntabstop(nicol, curwp->w_bufp->b_tabw);
+ else
+ ++nicol;
}
(void)delwhite(FFRAND, 1);
@@ -472,11 +482,17 @@ backdel(int f, int n)
int
space_to_tabstop(int f, int n)
{
+ int c;
+
if (n < 0)
return (FALSE);
if (n == 0)
return (TRUE);
- return (linsert((n << 3) - (curwp->w_doto & 7), ' '));
+
+ c = curwp->w_doto;
+ while (n-- > 0)
+ c = ntabstop(c, curbp->b_tabw);
+ return (linsert(c - curwp->w_doto, ' '));
}
/*