Re: [PATCH] Parent match
Dear Kyle,
On Thu, Nov 13, 2008 at 10:04:20AM -0600, Kyle Wheeler wrote:
> On Thursday, November 13 at 12:17 PM, quoth Jeremie Le Hen:
> > Attached you will find a patch introducing a new match pattern: =().
> > Thanks to this pattern you can match the parent message of messages
> > matching the inner pattern.
>
> I don't disagree with the idea, but I do disagree with the syntax. All the
> other patterns use ~, =, and % to differentiate between different ways of
> matching the same information. For example, ~c uses a regex to search the CC
> headers, =c performs a string-based match on the CC headers, and %c performs
> a group-based match on the CC headers. This is consistent across all of the
> various letters that can be used: %c, %C, %e, and %f are all group-based
> variants of the ~ versions of those same searches. I don't think it's wise
> to create a new pattern that appears to be the same sort of variation but
> does not behave in the same way. =() looks like it will be a string-based
> version of ~(), even if that doesn't necessarily make any sense. I think it
> would be smarter to change the brackets; make the pattern be ~{} or ~[]
> instead.
Thanks for this enlightenment. I didn't grasp this while reading the
manual page. I've created a new patch following your advices. I tested
it locally, it works.
I'm a little bit worried about the few number of enclosing character
pairs available. ~() is already taken, my patch gets its hand on ~[].
~{} and maybe ~`' remain, but it's not much. I hope there won't be a
too big need of them in the future.
Regards,
--
Jeremie Le Hen
< jeremie at le-hen dot org >< ttz at chchile dot org >
diff -urp mutt-1.5.18/doc/muttrc.man.head
mutt-1.5.18-parent_match/doc/muttrc.man.head
--- mutt-1.5.18/doc/muttrc.man.head 2008-01-28 03:20:21.000000000 +0100
+++ mutt-1.5.18-parent_match/doc/muttrc.man.head 2008-11-13
18:02:26.000000000 +0100
@@ -577,6 +577,9 @@ unreferenced message (requries threaded
.TP
~(PATTERN)
messages in threads containing messages matching a certain pattern, e.g. all
threads containing messages from you: ~(~P)
+.TP
+~[PATTERN]
+parent message of messages matching a certain pattern, e.g. all parent
messages having duplicates messages: =(~=)
.PD 1
.DT
.PP
diff -urp mutt-1.5.18/mutt.h mutt-1.5.18-parent_match/mutt.h
--- mutt-1.5.18/mutt.h 2008-01-30 05:26:50.000000000 +0100
+++ mutt-1.5.18-parent_match/mutt.h 2008-11-12 14:28:07.000000000 +0100
@@ -212,6 +212,7 @@ enum
M_AND,
M_OR,
M_THREAD,
+ M_PARENT,
M_TO,
M_CC,
M_COLLAPSED,
diff -urp mutt-1.5.18/pattern.c mutt-1.5.18-parent_match/pattern.c
--- mutt-1.5.18/pattern.c 2008-01-30 05:26:51.000000000 +0100
+++ mutt-1.5.18-parent_match/pattern.c 2008-11-13 18:01:40.000000000 +0100
@@ -730,15 +730,15 @@ static struct pattern_flags *lookup_tag
return NULL;
}
-static /* const */ char *find_matching_paren (/* const */ char *s)
+static /* const */ char *find_matching_paren (/* const */ char *s, char open,
char close)
{
int level = 1;
for (; *s; s++)
{
- if (*s == '(')
+ if (*s == open)
level++;
- else if (*s == ')')
+ else if (*s == close)
{
level--;
if (!level)
@@ -782,6 +782,7 @@ pattern_t *mutt_pattern_comp (/* const *
int alladdr = 0;
int or = 0;
int implicit = 1; /* used to detect logical AND operator */
+ char opench, closech;
struct pattern_flags *entry;
char *p;
char *buf;
@@ -833,18 +834,20 @@ pattern_t *mutt_pattern_comp (/* const *
case '%':
case '=':
case '~':
- if (*(ps.dptr + 1) == '(')
+ if (*(ps.dptr + 1) == '(' || *(ps.dptr + 1) == '[')
{
ps.dptr ++; /* skip ~ */
- p = find_matching_paren (ps.dptr + 1);
- if (*p != ')')
+ opench = *ps.dptr;
+ closech = opench == '(' ? ')' : ']';
+ p = find_matching_paren (ps.dptr + 1, opench, closech);
+ if (*p != closech)
{
snprintf (err->data, err->dsize, _("mismatched brackets: %s"),
ps.dptr);
mutt_pattern_free (&curlist);
return NULL;
}
tmp = new_pattern ();
- tmp->op = M_THREAD;
+ tmp->op = opench == '(' ? M_THREAD : M_PARENT;
if (last)
last->next = tmp;
else
@@ -927,7 +930,7 @@ pattern_t *mutt_pattern_comp (/* const *
implicit = 1;
break;
case '(':
- p = find_matching_paren (ps.dptr + 1);
+ p = find_matching_paren (ps.dptr + 1, '(', ')');
if (*p != ')')
{
snprintf (err->data, err->dsize, _("mismatched parenthesis: %s"),
ps.dptr);
@@ -1087,6 +1090,29 @@ static int match_threadcomplete(struct p
return 0;
}
+static int match_directchilds(struct pattern_t *pat, pattern_exec_flag flags,
CONTEXT *ctx, THREAD *t)
+{
+ HEADER *h;
+
+ /* Not sure this is needed, but harmless anyway */
+ if (!t)
+ return 0;
+ if (!t->child)
+ return 0;
+ t = t->child;
+ /* Not sure this is needed, but harmless anyway */
+ while (t->prev)
+ t = t->prev;
+ while (t) {
+ h = t->message;
+ if(h)
+ if(mutt_pattern_exec(pat, flags, ctx, h))
+ return 1;
+ t = t->next;
+ }
+ return 0;
+}
+
/* flags
M_MATCH_FULL_ADDRESS match both personal and machine address */
int
@@ -1100,6 +1126,8 @@ mutt_pattern_exec (struct pattern_t *pat
return (pat->not ^ (perform_or (pat->child, flags, ctx, h) > 0));
case M_THREAD:
return (pat->not ^ match_threadcomplete(pat->child, flags, ctx,
h->thread, 1, 1, 1, 1));
+ case M_PARENT:
+ return (pat->not ^ match_directchilds(pat->child, flags, ctx,
h->thread));
case M_ALL:
return (!pat->not);
case M_EXPIRED: