ref: ed0a057803a11e12326211123433100647d6c8f9
parent: 8c81b45793912daa0c3a27eba1859b3b42bfeb38
author: Ori Bernstein <ori@eigenstate.org>
date: Sat Nov 21 15:29:21 EST 2020
mbox: custom format strings.
--- a/mbox.c
+++ b/mbox.c
@@ -26,6 +26,7 @@
char *maildir = "/mail/fs";
char *mailbox = "mbox";
+char *listfmt = "%>40s\t<%f>";
Mesg dead = {.messageid="", .hash=42};
Reprog *addrpat;
@@ -435,32 +436,146 @@
qsort(mbox.mesg, mbox.nmesg, sizeof(Mesg*), cmpmesg);
}
+static char*
+getflag(Mesg *m)
+{
+ char* flag;
+
+ flag = "★";
+ if(m->flags & Fseen) flag = " ";
+ if(m->flags & Fresp) flag = "←";
+ if(m->flags & Fdel) flag = "∉";
+ if(m->flags & Ftodel) flag = "∉";
+ return flag;
+}
+
static void
-showmesg(Biobuf *bfd, Mesg *m, int depth, int recurse)
+printw(Biobuf *bp, char *s, int width)
{
- char *sep, *flag, *dots;
- int i, width;
+ char *dots;
- if(!(m->state & Sdummy)){
+ if(width <= 0)
+ Bprint(bp, "%s", s);
+ else{
dots = "";
- flag = "★";
- sep = depth ? "\t" : "";
- width = depth ? Subjlen - 4 : Subjlen;
- if(m->flags & Fseen) flag = " ";
- if(m->flags & Fresp) flag = "←";
- if(m->flags & Fdel) flag = "∉";
- if(m->flags & Ftodel) flag = "∉";
- if(utflen(m->subject) > Subjlen){
+ if(utflen(s) > width){
width -= 3;
dots = "...";
}
+ Bprint(bp, "%*.*s%s", -width, width, s, dots);
+ }
+}
- Bprint(bfd, "%-6s\t%s %s%*.*s%s\t<%s>\n",
- m->name,
- flag, sep, -width, width,
- m->subject,
- dots,
- m->from);
+/*
+ * Message format string:
+ * ======================
+ * %s: subject
+ * %f: from address
+ * %F: name + from address
+ * %t: to address
+ * %c: CC address
+ * %r: replyto address
+ * %[...]: string to display for child messages
+ * %{...}: date format string
+ */
+static void
+fmtmesg(Biobuf *bp, char *fmt, Mesg *m, int depth)
+{
+ char *p, *e, buf[64];
+ int width, i, indent;
+ Tm tm;
+
+ Bprint(bp, "%-6s\t%s ", m->name, getflag(m));
+ for(p = fmt; *p; p++){
+ if(*p != '%'){
+ Bputc(bp, *p);
+ continue;
+ }
+ p++;
+ width = 0;
+ indent = 0;
+ while(*p == '>'){
+ p++;
+ indent++;
+ }
+ while('0'<=*p && *p<='9')
+ width = width * 10 + *p++ - '0';
+ for(i = 0; indent && i < depth; i++){
+ Bputc(bp, '\t');
+ width -= 4;
+ if(indent == 1)
+ break;
+ }
+ switch(*p){
+ case '%':
+ Bprint(bp, "%%");
+ break;
+ case 'i':
+ if(depth > 0)
+ depth = 1;
+ case 'I':
+ for(i = 0; i < depth; i++){
+ if(width>0)
+ Bprint(bp, "%*s", width, "");
+ else
+ Bprint(bp, "\t");
+ }
+ break;
+ case 's':
+ printw(bp, m->subject, width);
+ break;
+ case 'f':
+ printw(bp, m->from, width);
+ break;
+ case 'F':
+ printw(bp, m->fromcolon, width);
+ break;
+ case 't':
+ printw(bp, m->to, width);
+ break;
+ case 'c':
+ printw(bp, m->cc, width);
+ break;
+ case 'r':
+ printw(bp, m->replyto, width);
+ break;
+ case '[':
+ if((e = strchr(p, ']')) == nil)
+ sysfatal("missing closing '}' in %%{");
+ if(e - p >= sizeof(buf) - 1)
+ sysfatal("%%{} contents too long");
+ snprint(buf, sizeof(buf), "%.*s", (int)(e - p), p);
+ if(depth > 0)
+ Bprint(bp, "%s", buf);
+ p = e;
+ break;
+ case '{':
+ p++;
+ if((e = strchr(p, '}')) == nil)
+ sysfatal("missing closing '}' in %%{");
+ if(e - p >= sizeof(buf) - 1)
+ sysfatal("%%{} contents too long");
+ snprint(buf, sizeof(buf), "%.*s", (int)(e - p), p);
+ tmtime(&tm, m->time, nil);
+ Bprint(bp, "%τ", tmfmt(&tm, buf));
+ p = e;
+ break;
+ default:
+ sysfatal("invalid directive '%%%c' in format string", *p);
+ break;
+ }
+ }
+ Bputc(bp, '\n');
+}
+
+
+static void
+showmesg(Biobuf *bfd, Mesg *m, int depth, int recurse)
+{
+ int i;
+
+ if(!(m->state & Sdummy)){
+ fmtmesg(bfd, listfmt, m, depth);
depth++;
}
if(recurse && mbox.view != Vflat)
@@ -858,7 +973,7 @@
static void
usage(void)
{
- fprint(2, "usage: %s [-T] [-f mailfs] [mbox]\n", argv0);
+ fprint(2, "usage: %s [-T] [-m mailfs] [-s] [-f format] [mbox]\n", argv0);
exits("usage");
}
@@ -870,16 +985,19 @@
int i;
mbox.view = Vgroup;
+ doquote = needsrcquote;
+ quotefmtinstall();
+ tmfmtinstall();
fmtstrinit(&fmt);
for(i = 0; i < argc; i++)
- fmtprint(&fmt, "%s ", argv[i]);
+ fmtprint(&fmt, "%q ", argv[i]);
cmd = fmtstrflush(&fmt);
if(cmd == nil)
sysfatal("out of memory");
ARGBEGIN{
- case 'f':
+ case 'm':
maildir = EARGF(usage());
break;
case 'T':
@@ -888,7 +1006,9 @@
case 's':
sender++;
break;
-
+ case 'f':
+ listfmt = EARGF(usage());
+ break;
default:
usage();
break;
@@ -898,10 +1018,6 @@
usage();
if(argc == 1)
mailbox = argv[0];
-
- doquote = needsrcquote;
- quotefmtinstall();
- tmfmtinstall();
addrpat = regcomp("[^ \t]*@[^ \t]*\\.[^ \t]*");
mesgpat = regcomp("[0-9]+(/.*)?");