From 6f00500070db7d65ae6c242f3a5c977205f28365 Mon Sep 17 00:00:00 2001 From: Kevin McCarthy Date: Wed, 5 Jul 2017 19:09:51 -0700 Subject: [PATCH] Add ~<() and ~>() immediate parent/children patterns. (closes #3144) Thanks to Jeremie Le Hen for the original patch, and for his persistence in getting this feature merged. --- doc/manual.xml.head | 14 ++++++++++++++ doc/muttrc.man.head | 6 ++++++ mutt.h | 2 ++ pattern.c | 38 +++++++++++++++++++++++++++++++++++++- 4 files changed, 59 insertions(+), 1 deletion(-) diff --git a/doc/manual.xml.head b/doc/manual.xml.head index 0a49a76ad..cc092c0e5 100755 --- a/doc/manual.xml.head +++ b/doc/manual.xml.head @@ -6601,6 +6601,20 @@ mailboxes $my_mx +mailbox3 PATTERN, e.g. all threads containing messages from you: ~(~P) + + ~<( + PATTERN) + messages whose immediate parent matches + PATTERN, e.g. replies to your messages: + ~<(~P) + + + ~>( + PATTERN) + messages having an immediate child matching + PATTERN, e.g. messages you replied to: + ~>(~P) + diff --git a/doc/muttrc.man.head b/doc/muttrc.man.head index 1cd2fafa3..487d0bf29 100644 --- a/doc/muttrc.man.head +++ b/doc/muttrc.man.head @@ -636,6 +636,12 @@ unreferenced message (requires threaded view) .TP ~(PATTERN) messages in threads containing messages matching a certain pattern, e.g. all threads containing messages from you: ~(~P) +.TP +~<(PATTERN) +messages whose immediate parent matches PATTERN, e.g. replies to your messages: ~<(~P) +.TP +~>(PATTERN) +messages having an immediate child matching PATTERN, e.g. messages you replied to: ~>(~P) .PD 1 .DT .PP diff --git a/mutt.h b/mutt.h index 57dc6c47f..04840ae7c 100644 --- a/mutt.h +++ b/mutt.h @@ -154,6 +154,8 @@ enum MUTT_AND, MUTT_OR, MUTT_THREAD, + MUTT_PARENT, + MUTT_CHILDREN, MUTT_TO, MUTT_CC, MUTT_COLLAPSED, diff --git a/pattern.c b/pattern.c index 77f8b5ed2..40dacaab9 100644 --- a/pattern.c +++ b/pattern.c @@ -1113,6 +1113,7 @@ struct Pattern *mutt_pattern_comp(/* const */ char *s, int flags, struct Buffer bool or = false; bool implicit = true; /* used to detect logical AND operator */ bool isalias = false; + short thread_op; const struct PatternFlags *entry = NULL; char *p = NULL; char *buf = NULL; @@ -1175,9 +1176,18 @@ struct Pattern *mutt_pattern_comp(/* const */ char *s, int flags, struct Buffer mutt_pattern_free(&curlist); return NULL; } + thread_op = 0; if (*(ps.dptr + 1) == '(') + thread_op = MUTT_THREAD; + else if ((*(ps.dptr + 1) == '<') && (*(ps.dptr + 2) == '(')) + thread_op = MUTT_PARENT; + else if ((*(ps.dptr + 1) == '>') && (*(ps.dptr + 2) == '(')) + thread_op = MUTT_CHILDREN; + if (thread_op) { ps.dptr++; /* skip ~ */ + if (thread_op == MUTT_PARENT || thread_op == MUTT_CHILDREN) + ps.dptr++; p = find_matching_paren(ps.dptr + 1); if (*p != ')') { @@ -1186,7 +1196,7 @@ struct Pattern *mutt_pattern_comp(/* const */ char *s, int flags, struct Buffer return NULL; } tmp = new_pattern(); - tmp->op = MUTT_THREAD; + tmp->op = thread_op; if (last) last->next = tmp; else @@ -1440,6 +1450,28 @@ static int match_threadcomplete(struct Pattern *pat, pattern_exec_flag flags, return 0; } +static int match_threadparent(struct Pattern *pat, pattern_exec_flag flags, + struct Context *ctx, struct MuttThread *t) +{ + if (!t || !t->parent || !t->parent->message) + return 0; + + return mutt_pattern_exec(pat, flags, ctx, t->parent->message, NULL); +} + +static int match_threadchildren(struct Pattern *pat, pattern_exec_flag flags, + struct Context *ctx, struct MuttThread *t) +{ + if (!t || !t->child) + return 0; + + for (t = t->child; t; t = t->next) + if (t->message && mutt_pattern_exec(pat, flags, ctx, t->message, NULL)) + return 1; + + return 0; +} + /* Sets a value in the PatternCache cache entry. * Normalizes the "true" value to 2. */ @@ -1480,6 +1512,10 @@ int mutt_pattern_exec(struct Pattern *pat, pattern_exec_flag flags, case MUTT_THREAD: return (pat->not ^ match_threadcomplete(pat->child, flags, ctx, h->thread, 1, 1, 1, 1)); + case MUTT_PARENT: + return (pat->not ^ match_threadparent(pat->child, flags, ctx, h->thread)); + case MUTT_CHILDREN: + return (pat->not ^ match_threadchildren(pat->child, flags, ctx, h->thread)); case MUTT_ALL: return !pat->not; case MUTT_EXPIRED: -- 2.40.0