Dear all, Following some back and forth on how disklabel output should be formatted, I proposed to Kenneth to extend the column(1) utility. All that was missing is the ability to right justify. I've longed for this feature for a while: I often use 'column -t' to prettify data coming from an awk pipeline.
Example: job@vurt ~$ netstat -r | column -t -r | tail -5 ff01::%iwm0/32 fe80::4708:d2be:9a Um 0 3 - 4 iwm0 ff01::%lo0/32 localhost Um 0 1 32768 4 lo0 ff02::/16 localhost UGRS 0 1 32768 8 lo0 ff02::%iwm0/32 fe80::4708:d2be:9a Um 0 3 - 4 iwm0 ff02::%lo0/32 localhost Um 0 1 32768 4 lo0 Patch courtesy of Kenneth R Westerback. OK? Index: column.1 =================================================================== RCS file: /cvs/src/usr.bin/column/column.1,v retrieving revision 1.18 diff -u -p -r1.18 column.1 --- column.1 24 Oct 2016 13:53:05 -0000 1.18 +++ column.1 4 Jul 2018 10:27:54 -0000 @@ -40,6 +40,7 @@ .Nm column .Op Fl tx .Op Fl c Ar columns +.Op Fl r Op Ar list .Op Fl s Ar sep .Op Ar .Sh DESCRIPTION @@ -66,6 +67,16 @@ The options are as follows: Output is formatted for a display .Ar columns wide. +.It Fl r Op Ar list +Table mode will right justify the column contents for the +specified columns. +.Ar list +is a list of comma separated column numbers or column ranges. +Column numbers start at 1. +The list must not contain whitespace. +If no +.Ar list +is provided then all columns will be right justified. .It Fl s Ar sep Specify a set of characters to delimit columns for the .Fl t Index: column.c =================================================================== RCS file: /cvs/src/usr.bin/column/column.c,v retrieving revision 1.26 diff -u -p -r1.26 column.c --- column.c 22 Jun 2018 12:27:00 -0000 1.26 +++ column.c 4 Jul 2018 10:28:00 -0000 @@ -47,7 +47,8 @@ void c_columnate(void); void *ereallocarray(void *, size_t, size_t); void input(FILE *); -void maketbl(void); +int rightjustify(const char *, const int); +void maketbl(const int, const char *); void print(void); void r_columnate(void); __dead void usage(void); @@ -69,8 +70,8 @@ main(int argc, char *argv[]) { struct winsize win; FILE *fp; - int ch, tflag, xflag; - char *p; + int ch, rflag, tflag, xflag; + char *p, *rcols; const char *errstr; setlocale(LC_CTYPE, ""); @@ -87,14 +88,19 @@ main(int argc, char *argv[]) if (pledge("stdio rpath", NULL) == -1) err(1, "pledge"); - tflag = xflag = 0; - while ((ch = getopt(argc, argv, "c:s:tx")) != -1) { + rcols = NULL; + rflag = 0; tflag = xflag = 0; + while ((ch = getopt(argc, argv, "c:r::s:tx")) != -1) { switch(ch) { case 'c': termwidth = strtonum(optarg, 1, INT_MAX, &errstr); if (errstr != NULL) errx(1, "%s: %s", errstr, optarg); break; + case 'r': + rflag = 1; + rcols = optarg; + break; case 's': if ((separator = reallocarray(NULL, strlen(optarg) + 1, sizeof(*separator))) == NULL) @@ -139,7 +145,7 @@ main(int argc, char *argv[]) return eval; if (tflag) - maketbl(); + maketbl(rflag, rcols); else if (*maxwidths >= termwidth) print(); else if (xflag) @@ -207,18 +213,69 @@ print(void) puts(table[row]->content); } +int +rightjustify(const char *rcols, const int col) +{ + const char *errstr; + char c, *num, *temp; + long long ch, rangestart; + unsigned int i; + + if (rcols == NULL) + return 1; + + temp = strdup(rcols); + num = temp; + rangestart = -1; + + c = 0; + for (i = 0; i <= strlen(rcols); i++) { + ch = temp[i]; + if (ch == ',' || ch == '-') + temp[i] = '\0'; + if (temp[i] != '\0') + continue; + + c = strtonum(num, 1, INT_MAX, &errstr); + if (errstr != NULL) + break; + c--; /* Users are 1-based. Reality is 0-based. */ + + if (c == col) + goto found; + if (ch == '-') { + rangestart = c; + } else if ((ch == ',' || ch == '\0') && rangestart != -1) { + if (rangestart <= col && c >= col) + goto found; + rangestart = -1; + } + num = temp + i + 1; + } + + free(temp); + return 0; +found: + free(temp); + return 1; +} void -maketbl(void) +maketbl(const int rflag, const char *rcols) { struct field **row; int col; for (row = table; entries--; ++row) { - for (col = 0; (*row)[col + 1].content != NULL; ++col) - printf("%s%*s ", (*row)[col].content, - maxwidths[col] - (*row)[col].width, ""); - puts((*row)[col].content); + for (col = 0; (*row)[col].content != NULL; ++col) { + if (rflag && rightjustify(rcols, col)) + printf("%*s ", maxwidths[col], + (*row)[col].content); + else + printf("%-*s ", maxwidths[col], + (*row)[col].content); + } + putchar('\n'); } }