aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDuncaen <mail@duncano.de>2016-07-23 17:40:29 +0200
committerChristian Neukirchen <chneukirchen@gmail.com>2016-07-28 17:32:24 +0200
commit418555f53a76f26f9527a43849172c9471b70f1e (patch)
tree8d30f7dba7644621f9e80890e75d58ce049fb0bb
parenteaa661050603a25f2b1a4de24c0c44ed0fb93de7 (diff)
downloadmblaze-418555f53a76f26f9527a43849172c9471b70f1e.tar.gz
mpick: add -T flag to pick whole thread if one message matches
-rw-r--r--mpick.c222
1 files changed, 185 insertions, 37 deletions
diff --git a/mpick.c b/mpick.c
index 752e980..6d77142 100644
--- a/mpick.c
+++ b/mpick.c
@@ -36,6 +36,7 @@ enum op {
EXPR_GLOBI,
EXPR_REGEX,
EXPR_REGEXI,
+ EXPR_PRUNE,
EXPR_PRINT,
EXPR_TYPE,
EXPR_ALLSET,
@@ -72,6 +73,9 @@ enum flags {
/* custom */
FLAG_NEW = 64,
FLAG_CUR = 128,
+
+ FLAG_PARENT = 256,
+ FLAG_CHILD = 512,
};
struct expr {
@@ -92,12 +96,29 @@ struct mailinfo {
time_t date;
int depth;
int index;
+ int replies;
+ int matched;
+ int prune;
long flags;
off_t total;
char subject[100];
};
+struct mlist {
+ struct mailinfo *m;
+ struct mlist *next;
+};
+
+struct thread {
+ int matched;
+ struct mlist childs[100];
+ struct mlist *cur;
+};
+
+static struct thread *thr;
+
static char *argv0;
+static int Tflag;
static long kept;
static long num;
@@ -106,6 +127,7 @@ static struct expr *expr;
static char *cur;
static char *pos;
static time_t now;
+static int prune;
static void
ws()
@@ -196,7 +218,10 @@ static struct expr *parse_or();
static struct expr *
parse_inner()
{
- if (token("print")) {
+ if (token("prune")) {
+ struct expr *e = mkexpr(EXPR_PRUNE);
+ return e;
+ } else if (token("print")) {
struct expr *e = mkexpr(EXPR_PRINT);
return e;
} else if (token("!")) {
@@ -688,6 +713,9 @@ eval(struct expr *e, struct mailinfo *m)
case EXPR_NOT:
return !eval(e->a.expr, m);
return 1;
+ case EXPR_PRUNE:
+ prune = 1;
+ return 1;
case EXPR_PRINT:
return 1;
case EXPR_LT:
@@ -759,8 +787,8 @@ eval(struct expr *e, struct mailinfo *m)
return 0;
}
-void
-oneline(char *line)
+struct mailinfo *
+mailfile(char *file)
{
static int init;
if (!init) {
@@ -772,60 +800,169 @@ oneline(char *line)
init = 1;
}
- struct mailinfo m;
-
- memset(m.subject, 0, sizeof m.subject);
- m.fpath = line;
- m.index = num++;
- m.flags = 0;
- m.depth = 0;
- m.sb = 0;
-
- while (*m.fpath == ' ' || *m.fpath== '\t') {
- m.depth++;
- m.fpath++;
+ struct mailinfo *m;
+ m = calloc(1, sizeof *m);
+ if (!m) {
+ fprintf(stderr, "calloc");
+ exit(2);
+ }
+ memset(m->subject, 0, sizeof m->subject);
+
+ m->fpath = file;
+ m->index = num++;
+ m->flags = 0;
+ m->depth = 0;
+ m->sb = 0;
+ m->msg = 0;
+
+ while (*m->fpath == ' ' || *m->fpath== '\t') {
+ m->depth++;
+ m->fpath++;
}
- char *e = m.fpath + strlen(m.fpath) - 1;
- while (m.fpath < e && (*e == ' ' || *e == '\t'))
+ char *e = m->fpath + strlen(m->fpath) - 1;
+ while (m->fpath < e && (*e == ' ' || *e == '\t'))
*e-- = 0;
- m.msg = blaze822(m.fpath);
- if (!m.msg)
- return;
+ m->msg = blaze822(m->fpath);
+ if (!m->msg)
+ return 0;
if ((e = strrchr(m->fpath, '/') - 1) && (e - m->fpath) >= 2 &&
*e-- == 'w' && *e-- == 'e' && *e-- == 'n')
- m.flags |= FLAG_NEW;
+ m->flags |= FLAG_NEW;
- if (cur && strcmp(cur, m.fpath) == 0)
- m.flags |= FLAG_CUR;
+ if (cur && strcmp(cur, m->fpath) == 0)
+ m->flags |= FLAG_CUR;
- char *f = strstr(m.fpath, ":2,");
+ char *f = strstr(m->fpath, ":2,");
if (f) {
if (strchr(f, 'P'))
- m.flags |= FLAG_PASSED;
+ m->flags |= FLAG_PASSED;
if (strchr(f, 'R'))
- m.flags |= FLAG_REPLIED;
+ m->flags |= FLAG_REPLIED;
if (strchr(f, 'S'))
- m.flags |= FLAG_SEEN;
+ m->flags |= FLAG_SEEN;
if (strchr(f, 'T'))
- m.flags |= FLAG_TRASHED;
+ m->flags |= FLAG_TRASHED;
if (strchr(f, 'D'))
- m.flags |= FLAG_DRAFT;
+ m->flags |= FLAG_DRAFT;
if (strchr(f, 'F'))
- m.flags |= FLAG_FLAGGED;
+ m->flags |= FLAG_FLAGGED;
+ }
+
+ return m;
+}
+
+void
+do_thr()
+{
+ struct mlist *ml;
+
+ if (!thr)
+ return;
+
+ for (ml = thr->childs; ml; ml = ml->next) {
+ if (!ml->m)
+ continue;
+ if ((ml->m->prune = prune) || (Tflag && thr->matched))
+ continue;
+ if (expr && eval(expr, ml->m)) {
+ ml->m->matched = 1;
+ thr->matched++;
+ }
+ }
+ prune = 0;
+
+ for (ml = thr->childs; ml; ml = ml->next) {
+ if (!ml->m)
+ break;
+
+ if (((Tflag && thr->matched) || ml->m->matched) && !ml->m->prune) {
+ int i;
+ for (i = 0; i < ml->m->depth; i++)
+ putchar(' ');
+
+ fputs(ml->m->fpath, stdout);
+ putchar('\n');
+
+ kept++;
+ }
+
+ /* free collected mails */
+ if (ml->m->msg)
+ blaze822_free(ml->m->msg);
+
+ if (ml->m->sb)
+ free(ml->m->sb);
+
+ free(ml->m->fpath);
+ free(ml->m);
+ }
+
+ free(thr);
+}
+
+void
+collect(char *file)
+{
+ struct mailinfo *m;
+ struct mlist *ml;
+
+ if ((m = mailfile(file)) == 0)
+ return;
+
+ if (m->depth == 0) {
+ if (thr)
+ do_thr();
+
+ /* new thread */
+ thr = calloc(1, sizeof *thr);
+ if (!thr) {
+ fprintf(stderr, "calloc");
+ exit(2);
+ }
+
+ thr->matched = 0;
+ thr->cur = thr->childs;
+ thr->cur->m = m;
+ } else {
+ ml = thr->cur + 1;
+ thr->cur->next = ml;
+ thr->cur = ml;
+ ml->m = m;
}
- if (expr && !eval(expr, &m))
+ m->fpath = strdup(m->fpath);
+
+ /* already one match in thread */
+ if (Tflag && thr->matched)
+ return;
+
+ if (expr && !eval(expr, m))
+ return;
+
+ thr->matched++;
+}
+
+void
+oneline(char *file)
+{
+ struct mailinfo *m;
+
+ if ((m = mailfile(file)) == 0)
+ return;
+
+ if (expr && !eval(expr, m))
goto out;
+ printf("%s\n", file);
kept++;
- printf("%s\n", line);
out:
- free(m.sb);
- blaze822_free(m.msg);
+ blaze822_free(m->msg);
+ free(m->sb);
+ free(m);
}
int
@@ -833,11 +970,13 @@ main(int argc, char *argv[])
{
long i;
int c;
+ void (*cb)(char *);
argv0 = argv[0];
- while ((c = getopt(argc, argv, "t:")) != -1)
+ while ((c = getopt(argc, argv, "Tt:")) != -1)
switch (c) {
+ case 'T': Tflag = 1; break;
case 't': expr = chain(expr, EXPR_AND, parse_expr(optarg)); break;
}
@@ -845,10 +984,19 @@ main(int argc, char *argv[])
for (c = optind; c < argc; c++)
expr = chain(expr, EXPR_AND, parse_msglist(argv[c]));
+ if (Tflag)
+ cb = collect;
+ else
+ cb = oneline;
+
if (isatty(0)) {
- i = blaze822_loop1(":", oneline);
+ i = blaze822_loop1(":", cb);
} else
- i = blaze822_loop(0, NULL, oneline);
+ i = blaze822_loop(0, NULL, cb);
+
+ /* print and free last thread */
+ if (Tflag && thr)
+ do_thr();
fprintf(stderr, "%ld mails tested, %ld picked.\n", i, kept);
return 0;