From: Nader Akoury <
g...@dojoteef.com>
Proton Mail adds fake message IDs into the References header. A
previous PR on Github that was never merged made a Proton Mail specific
fix. I've instead introduced a generic regex filter that allows
filtering out the refs like so:
> mthread -m '@protonmail.(internal|conversation)id'
---
man/mthread.1 | 24 +++++++++++++++++++++++-
mthread.c | 47 +++++++++++++++++++++++++++++++++++++++--------
2 files changed, 62 insertions(+), 9 deletions(-)
diff --git a/man/mthread.1 b/man/mthread.1
index 00bef88..e6d0da5 100644
--- a/man/mthread.1
+++ b/man/mthread.1
@@ -6,7 +6,8 @@
.Nd arrange messages into discussions
.Sh SYNOPSIS
.Nm
-.Op Fl vpr
+.Op Fl vpri
+.Op Fl m Ar regex
.Op Fl S Ar msg
.Op Ar msgs\ ...
.Sh DESCRIPTION
@@ -39,6 +40,22 @@ With
only add parents, not unrelated subthreads.
.It Fl r
Sort the top-level threads in reverse order (newest threads first).
+.It Fl i
+Match
+.Fl m Ar regex
+case insensitively. Should be specified before the
+.Fl m
+flag.
+.It Fl m Ar regex
+Use
+.Ar regex
+to filter out matching references in messages. Can be
+specified multiple times. The
+.Ar regex
+applies to all the following Maildir folders on the command line,
+until another
+.Fl m
+supersedes it.
.It Fl S Ar msg
Treat
.Ar msg
@@ -52,6 +69,11 @@ completing threads where your replies were missing.
.El
.Sh EXIT STATUS
.Ex -std
+.Sh EXAMPLES
+You can ignore Proton Mail's fake references used for tracking.
+.Pp
+.Dl mthread -m '@protonmail\.(internal|conversation)id'
+.Pp
.Sh SEE ALSO
.Xr mmsg 7
.Pp
diff --git a/mthread.c b/mthread.c
index 77fb21e..6835080 100644
--- a/mthread.c
+++ b/mthread.c
@@ -1,15 +1,17 @@
/* jwz-style threading
- * clean-room implementation of
https://www.jwz.org/doc/threading.html
- * without looking at any code
- *
- * subject threading and sibling sorting is not done yet
- */
+ * clean-room implementation of
https://www.jwz.org/doc/threading.html
+ * without looking at any code
+ *
+ * subject threading and sibling sorting is not done yet
+ */
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
+#include <locale.h>
+#include <regex.h>
#include <search.h>
#include <stdint.h>
#include <stdio.h>
@@ -24,6 +26,7 @@
static int vflag;
static int pflag;
static int rflag;
+static int iflag;
static int optional;
struct container {
@@ -37,6 +40,7 @@ struct container {
};
static void *mids;
+static regex_t *mfilter;
int
midorder(const void *a, const void *b)
@@ -159,6 +163,9 @@ thread(char *file)
mid = strndup(m+1, v-m-1);
// XXX free?
+ if (mfilter && regexec(mfilter, mid, 0, 0, 0) == 0)
+ continue;
+
me = midcont(mid);
if (me == c)
@@ -410,33 +417,57 @@ print_tree(struct container *c, int depth)
} while ((c = c->next));
}
+void
+build_filter(const char *regexstr) {
+ if (mfilter) {
+ regfree(mfilter);
+ mfilter = 0;
+ }
+
+ if (regexstr) {
+ mfilter = malloc(sizeof (regex_t));
+ int r = regcomp(mfilter, regexstr, REG_NOSUB | REG_EXTENDED | iflag);
+ if (r != 0) {
+ char buf[256];
+ regerror(r, mfilter, buf, sizeof buf);
+ fprintf(stderr, "mthread: regex error: %s\n", buf);
+ exit(2);
+ }
+ }
+}
+
int
main(int argc, char *argv[])
{
+ setlocale(LC_ALL, ""); // for localized regexp
+
int c;
optional = 1;
xpledge("stdio rpath", "");
- while ((c = getopt(argc, argv, "S:prv")) != -1)
+ while ((c = getopt(argc, argv, "im:S:prv")) != -1)
switch (c) {
+ case 'i': iflag = REG_ICASE; break;
+ case 'm': build_filter(optarg); break;
case 'S': blaze822_loop1(optarg, thread); break;
case 'v': vflag = 1; break;
case 'p': pflag = 1; break;
case 'r': rflag = 1; break;
default:
- fprintf(stderr, "Usage: mthread [-vpr] [-S dir] [msgs...]\n");
+ fprintf(stderr, "Usage: mthread [-vpri] [-S dir] [-m regex] [msgs...]\n");
exit(1);
}
optional = 0;
-
if (argc == optind && isatty(0))
blaze822_loop1(":", thread);
else
blaze822_loop(argc-optind, argv+optind, thread);
+ build_filter(0);
+
// the tree of all toplevel threads has depth -1,
// so toplevel threads have depth 0.
--
2.50.0