about summary refs log tree commit diff
path: root/mscan.c
diff options
context:
space:
mode:
authorChristian Neukirchen <chneukirchen@gmail.com>2016-08-04 18:59:46 +0200
committerChristian Neukirchen <chneukirchen@gmail.com>2016-08-04 18:59:46 +0200
commitf628a10ff6c8e359036984c0a37a9cd1d3784914 (patch)
treec37ce1663c96c484400281265a62d22f2d1335df /mscan.c
parent688dd618180b5801a0ec7382b3745f4699a14f9b (diff)
downloadmblaze-f628a10ff6c8e359036984c0a37a9cd1d3784914.tar.gz
mblaze-f628a10ff6c8e359036984c0a37a9cd1d3784914.tar.xz
mblaze-f628a10ff6c8e359036984c0a37a9cd1d3784914.zip
mscan: use format strings
Diffstat (limited to 'mscan.c')
-rw-r--r--mscan.c254
1 files changed, 197 insertions, 57 deletions
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);
 		}