aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2022-05-13 07:15:16 -0700
committerKaz Kylheku <kaz@kylheku.com>2022-05-13 07:15:16 -0700
commit297cf626809f27e3543576cb3547eb1868b663c8 (patch)
treefb594eb7a9641c4ba61ea82f0028b2915d79d785
parent8a337f186d99881114ceefb02a513db48f97408f (diff)
downloadpw-297cf626809f27e3543576cb3547eb1868b663c8.tar.gz
pw-297cf626809f27e3543576cb3547eb1868b663c8.tar.bz2
pw-297cf626809f27e3543576cb3547eb1868b663c8.zip
Expand tabs to spaces, with configurable tab size.
-rw-r--r--pw.139
-rw-r--r--pw.c45
2 files changed, 64 insertions, 20 deletions
diff --git a/pw.1 b/pw.1
index 21a6d56..79a1617 100644
--- a/pw.1
+++ b/pw.1
@@ -114,15 +114,25 @@ trimmed, it is terminated by the
character to indicate that there are more characters. The display may be
scrolled interactively to read the long lines.
-The ASCII DEL character (127) is displayed as
+Control characters are replaced as follows. The ASCII
+.I DEL
+character (127) is converted to the character sequence
.B ^?
-and ASCII control characters are displayed as
+and other ASCII control characters are converted to
.BR ^@ ,
.BR ^A ", ..."
.BR ^Z ", ..."
-.BR ^_ .
-All other characters are sent to the display as-is. No attempt is made
-to account for the width of East Asian Unicode characters, and such.
+.BR ^_ ,
+except for
+.I TAB
+which is expanded into spaces according to the current tab stop.
+All other characters remain as-is. No attempt is made to account for the width
+of East Asian Unicode characters, and such.
+
+The above replacement of control characters happens when lines are read from
+the input source, not when they are being displayed. Therefore, changing
+the tab stop size has no effect on lines which are already captured and
+displayed.
When the display is scrolled horizontally, the
.B >
@@ -251,6 +261,12 @@ and
characters which indicate line truncation and pane separation are
shown in inverse video (dark foreground, light background).
+.IP [\fIcount\fP]\fBt\fP
+Set the tab stop size. If count is omitted, zero, or greater than 16,
+then the value 8 is substituted. The tab stop size does not affect lines
+which have already been captured and displayed; tabs are expanded to spaces
+when lines are read from standard input and entered into the FIFO.
+
.IP \fBCtrl-G\fP
Shows the status of the display parameters, in a form which can be
given to the
@@ -669,7 +685,7 @@ the trigger count is reset to zero. Thus when the
command is used to resume capture, the same number of capture events
will have to occur again before the next automatic suspension.
-.IP "\fB:p\fP [\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP]]]]]
+.IP "\fB:p\fP [\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP]]]]]]
Sets the display parameters, exactly in the manner of the
.B -p
option. Any parameters not specified are reset to their default initial values:
@@ -837,7 +853,7 @@ option. If neither option is used, then
.I pattern
is interpreted as a BRE.
-.IP "\fB-p\fP [\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP]]]]]
+.IP "\fB-p\fP [\fIinteger\fP[,[\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP[,\fIinteger\fP]]]]]]
Specify the display parameters, as comma-separated non-negative integers.
The meaning of these integer values is:
.RS
@@ -846,9 +862,9 @@ horizontal scroll position;
.IP 2.
width of left pane;
.IP 3.
-width of middle pane; and
+width of middle pane;
.IP 4.
-middle pane view offset; and
+middle pane view offset;
.IP 5.
bitmask of several flags controlling line number display
.RB ( #
@@ -856,13 +872,16 @@ command), highlighting
.RB ( Ctrl-I/Tab
command), and suspended mode
.RB ( Space
-command). The values are internal and undocumented.
+command), the values being internal and undocumented; and
+.IP 6.
+the tab stop size.
.PP
All five numbers are optional, and default to zero if omitted. Since
.B -p
requires an argument, the only way all four may be omitted is if a blank
or empty argument is given.
+The tab stop must be in the range 0 to 16. A value of 0 is interpreted as 8.
The
.B Ctrl-G
command displays these same parameters in the same format, so it is possible to
diff --git a/pw.c b/pw.c
index 5e52a6c..1abe3d0 100644
--- a/pw.c
+++ b/pw.c
@@ -47,6 +47,7 @@
#define ctrl(ch) ((ch) & 0x1f)
#define BS 8
+#define TAB 9
#define CR 13
#define ESC 27
#define DEL 127
@@ -94,6 +95,7 @@ typedef struct pwstate {
int vsplit1, vsplit2, vs2pos;
int hist;
int columns;
+ int tstop;
unsigned stat;
int sncount, tcount;
char *curcmd, *savedcmd;
@@ -256,16 +258,25 @@ static char *addch(char *line, int ch)
abort();
}
-static char *addchesc(char *line, int ch)
+static char *addchesc(char *line, int tstop, int ch)
{
- if (ch == DEL) {
+ switch (ch) {
+ case DEL:
line = addch(line, '^');
line = addch(line, '?');
- } else if (ch < 32) {
- line = addch(line, '^');
- line = addch(line, ch + 64);
- } else {
+ break;
+ case TAB:
+ for (size_t len = dslen(line); line = addch(line, ' '), ++len % tstop != 0;)
+ /* empty */;
+ break;
+ default:
+ if (ch < 32) {
+ line = addch(line, '^');
+ line = addch(line, ch + 64);
+ break;
+ }
line = addch(line, ch);
+ break;
}
return line;
@@ -682,6 +693,7 @@ static int decodeparms(pwstate *pw, char *parms,
char *rpane = strtok(0, ", \t");
char *vs2pos = strtok(0, ", \t");
char *flags = strtok(0, ", \t");
+ char *tstop = strtok(0, ", \t");
pw->hpos = pw->vsplit1 = pw->vsplit2 = pw->vs2pos = 0;
pw->stat &= ~stat_save;
@@ -715,6 +727,13 @@ static int decodeparms(pwstate *pw, char *parms,
pw->stat |= (stat & stat_save);
}
+ if (tstop && ((pw->tstop = getznn(tstop, &err)) < 0 || pw->tstop > 16)) {
+ snprintf(resbuf, size, "bad tab stop size%s: %s\n", tstop, err);
+ if (pw->tstop == 0)
+ pw->tstop = 8;
+ return 0;
+ }
+
return 1;
}
@@ -898,8 +917,8 @@ static execode execute(pwstate *pw, char *cmd, char *resbuf,
break;
}
- fprintf(f, ":p%d,%d,%d,%d,%d\n", pw->hpos, pw->vsplit1, pw->vsplit2,
- pw->vs2pos, (int) pw->stat & stat_save);
+ fprintf(f, ":p%d,%d,%d,%d,%d,%d\n", pw->hpos, pw->vsplit1, pw->vsplit2,
+ pw->vs2pos, (int) pw->stat & stat_save, pw->tstop);
if (pw->tcount)
fprintf(f, ":f%d\n", pw->tcount);
@@ -1086,7 +1105,7 @@ void clipsplits(pwstate *pw)
int main(int argc, char **argv)
{
- struct pwstate pw = { .columns = 80, .maxlines = 15 };
+ struct pwstate pw = { .columns = 80, .maxlines = 15, .tstop = 8 };
char *line = 0;
FILE *tty = fopen("/dev/tty", "r+");
int maxed = 0;
@@ -1321,7 +1340,7 @@ int main(int argc, char **argv)
if ((pw.stat & stat_eof) == 0) {
int ch;
while ((ch = getc(stdin)) != EOF && ch != '\n' && dslen(line) < maxlen)
- line = addchesc(line, ch);
+ line = addchesc(line, pw.tstop, ch);
if (ch == EOF) {
if (feof(stdin) || (errno != EAGAIN && errno != EWOULDBLOCK)) {
nfds = 1;
@@ -1617,6 +1636,12 @@ int main(int argc, char **argv)
if ((pw.stat & stat_eof) == 0)
pw.stat |= stat_susp;
break;
+ case 't':
+ if (cmdcount < 1 || cmdcount > 16)
+ cmdcount = 8;
+ pw.tstop = cmdcount;
+ pw.stat |= stat_force;
+ break;
case CR:
pw.stat &= ~stat_susp;
break;