From f628a10ff6c8e359036984c0a37a9cd1d3784914 Mon Sep 17 00:00:00 2001 From: Christian Neukirchen Date: Thu, 4 Aug 2016 18:59:46 +0200 Subject: mscan: use format strings --- mscan.c | 254 +++++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 197 insertions(+), 57 deletions(-) (limited to 'mscan.c') diff --git a/mscan.c b/mscan.c index 6bc7d4c..4023910 100644 --- a/mscan.c +++ b/mscan.c @@ -29,6 +29,8 @@ static int Iflag; static int nflag; static int curyear; static int curyday; +static char default_fflag[] = "%c%m %-3n %10d %17f %t %2i%s"; +static char *fflag = default_fflag; void u8putstr(FILE *out, char *s, ssize_t l, int pad) @@ -95,11 +97,63 @@ numline(char *file) printf("%s\n", file); } +static char * +fmt_date(struct message *msg, int w, int iso) +{ + static char date[32]; + char *v; + + if (!msg) + return ""; + + if ((v = blaze822_hdr(msg, "date"))) { + time_t t = blaze822_date(v); + if (t != -1) { + struct tm *tm; + tm = localtime(&t); + + if (iso && w >= 19) + strftime(date, sizeof date, "%Y-%m-%d %H:%M:%S", tm); + else if (iso || tm->tm_year != curyear) + strftime(date, sizeof date, "%Y-%m-%d", tm); + else if (tm->tm_yday != curyday) + strftime(date, sizeof date, "%a %b %e", tm); + else + strftime(date, sizeof date, "%a %H:%M", tm); + } else { + strcpy(date, "(invalid)"); + } + } else { + strcpy(date, "(unknown)"); + // mtime perhaps? + } + + return date; +} + +static void +print_human(intmax_t i) +{ + double d = i / 1024.0; + const char *u = "\0\0M\0G\0T\0P\0E\0Z\0Y\0"; + while (d >= 1024) { + u += 2; + d /= 1024.0; + } + + if (d < 1.0) + printf("%4.2f", d); + else if (!*u) + printf("%4.0f", d); + else if (d < 10.0) + printf("%3.1f%s", d, u); + else + printf("%3.0f%s", d, u); +} + void oneline(char *file) { - int metawidth = 38; - if (!init) { // delay loading of the seq until we need to scan the first // file, in case someone in the pipe updated the map before @@ -114,69 +168,41 @@ oneline(char *file) indent++; file++; } - indent *= 2; char *e = file + strlen(file) - 1; while (file < e && (*e == ' ' || *e == '\t')) *e-- = 0; struct message *msg = blaze822(file); - if (!msg) { - int p = cols-metawidth-3-indent; - printf("%*.*s\\_ %*.*s\n", -metawidth - indent, metawidth + indent, "", - -p, p, file); - return; - } + if (!msg) + goto nomsg; char flag1, flag2, flag3; - char *f = strstr(file, ":2,"); - if (!f) - f = ""; + char *flags = strstr(file, ":2,"); + if (!flags) + flags = ""; + else + flags += 3; if (cur && strcmp(cur, file) == 0) flag1 = '>'; - else if (!strchr(f, 'S')) + else if (!strchr(flags, 'S')) flag1 = '.'; - else if (strchr(f, 'T')) + else if (strchr(flags, 'T')) flag1 = 'x'; else flag1 = ' '; - if (strchr(f, 'F')) + if (strchr(flags, 'F')) flag2 = '*'; - else if (strchr(f, 'R')) + else if (strchr(flags, 'R')) flag2 = '-'; else flag2 = ' '; - char date[32]; char *v; - if ((v = blaze822_hdr(msg, "date"))) { - time_t t = blaze822_date(v); - if (t != -1) { - struct tm *tm; - tm = localtime(&t); - - if (Iflag > 1) { - strftime(date, sizeof date, - "%Y-%m-%d %H:%M:%S", tm); - metawidth += 9; - } else if (Iflag || tm->tm_year != curyear) - strftime(date, sizeof date, "%Y-%m-%d", tm); - else if (tm->tm_yday != curyday) - strftime(date, sizeof date, "%a %b %e", tm); - else - strftime(date, sizeof date, "%a %H:%M", tm); - } else { - strcpy(date, "(invalid)"); - } - } else { - strcpy(date, "(unknown)"); - // mtime perhaps? - } - flag3 = ' '; if (alias_idx) { if ((v = blaze822_hdr(msg, "to")) && itsme(v)) @@ -217,21 +243,134 @@ oneline(char *file) blaze822_decode_rfc2047(subjdec, subj, sizeof subjdec - 1, "UTF-8"); long lineno = blaze822_seq_find(file); - if (lineno) - printf("%c%c %-3ld %-10s ", flag1, flag2, lineno, date); - else - printf("%c%c %-10s ", flag1, flag2, date); - u8putstr(stdout, fromdec, 16, 1); - printf(" %c ", flag3); - int z; - if (indent > 18) { - printf("..%2d.. ", indent/2); - indent = 20; - } else { - for (z = 0; z < indent; z++) - printf(" "); + + if (0) { +nomsg: + flag1 = flag2 = flag3 = ' '; + *fromdec = 0; + snprintf(subjdec, sizeof subjdec, "\\_ %s", file); + lineno = 0; } - u8putstr(stdout, subjdec, cols-metawidth-indent, 0); + + int wleft = cols; + + char *f; + for (f = fflag; *f; f++) { + if (*f != '%') { + putchar(*f); + wleft--; + continue; + } + f++; + + int w = 0; + if ((*f >= '0' && *f <= '9') || *f == '-') { + errno = 0; + char *e; + w = strtol(f, &e, 10); + if (errno != 0) + w = 0; + else + f = e; + } + + if (!*f) + break; + + switch(*f) { + case '%': + putchar('%'); + wleft--; + break; + case 'c': + putchar(flag1); + wleft--; + break; + case 'm': + putchar(flag2); + wleft--; + break; + case 'M': + if (!w) w = -3; + wleft -= printf("%.*s", w, flags); + break; + case 'n': + if (lineno) + printf("%*ld", w, lineno); + else + printf("%*s", w, ""); + wleft -= w > 0 ? w : -w; + break; + case 'd': + case 'D': + if (!w) w = 10; + wleft -= printf("%*s", w, + fmt_date(msg, w, Iflag || *f == 'D')); + break; + case 'f': + u8putstr(stdout, fromdec, w ? w : 16, 1); + wleft -= w > 0 ? w : -w; + break; + case 't': + putchar(flag3); + wleft--; + break; + case 'i': + { + int z; + if (!w) + w = 1; + + if (indent >= 10) { + wleft -= printf("..%2d..", indent); + indent = 10 - 6/w; + } + + for (z = 0; z < w*indent; z++) + putchar(' '); + wleft -= w*indent; + } + break; + case 's': + if (!w) w = wleft; + u8putstr(stdout, subjdec, wleft, 0); + wleft -= w; + break; + case 'b': + { + struct stat st; + if (stat(file, &st) != 0) + st.st_size = 0; + print_human(st.st_size); + wleft -= 5; + } + break; + case 'F': + { + if (!w) w = 10; + char *e = file + strlen(file); + while (file < e && *e != '/') + e--; + e--; + while (file < e && *e != '/') + e--; + char *b = e - 1; + while (file < b && *b != '/') + b--; + if (*b == '/') + b++; + if (*b == '.') + b++; + wleft -= printf("%*.*s", w, e-b, b); + } + break; + default: + putchar('%'); + putchar(*f); + wleft -=2; + } + } + printf("\n"); blaze822_free(msg); @@ -241,12 +380,13 @@ int main(int argc, char *argv[]) { int c; - while ((c = getopt(argc, argv, "In")) != -1) + while ((c = getopt(argc, argv, "If:n")) != -1) switch(c) { case 'I': Iflag++; break; + case 'f': fflag = optarg; break; case 'n': nflag = 1; break; default: - fprintf(stderr, "Usage: mscan [-n] [-I] [msgs...]\n"); + fprintf(stderr, "Usage: mscan [-n] [-f format] [-I] [msgs...]\n"); exit(1); } -- cgit 1.4.1