From 1d48603f0e14dd31feb3dd940e6512ea40698bf1 Mon Sep 17 00:00:00 2001 From: Kevin Velghe Date: Mon, 15 Aug 2016 00:24:20 +0200 Subject: [PATCH] notmuch: Synchronise tags to flags Currently, flags are synced to tags, but the reverse isn't true. If you mark a mail as unread "the mutt way", you'll be able to find this mail using tag:unread, however if you remove the tag unread, the flags aren't adjusted, and it's still marked unread in mutt. This functionality is provided by notmuch, but means that any mail has to be synced to disc when the labels are modified, which conflicts with the way synchronisation to disk works in mutt. To solve this properly, it's best to just check if the changes performed in the tags involve some flags handled by mutt, and if so, update the header in mutt. When mutt syncs to disc, the flags will be adjusted on disc as well. Some remarks: - The parsing code is currently duplicated. I'll fix this. - The labels are currently hard-coded. It seems like notmuch doesn't allow customisation of these labels, but mutt-kz does for unread. - The draft and passed labels are currently ignored, as they aren't handled by mutt. Closes: karelzak/mutt-kz#148 --- mutt_notmuch.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 52 insertions(+) diff --git a/mutt_notmuch.c b/mutt_notmuch.c index e592dbdbe..097ec0205 100644 --- a/mutt_notmuch.c +++ b/mutt_notmuch.c @@ -1320,6 +1320,57 @@ static int update_tags(notmuch_message_t *msg, const char *tags) return 0; } +/* TODO: extract parsing of string to separate function, join + * update_header_tags and update_header_flags, which are given an array of + * tags. */ +static int update_header_flags(CONTEXT *ctx, HEADER *hdr, const char *tags) +{ + char *tag = NULL, *end = NULL, *p; + char *buf = safe_strdup(tags); + + if (!buf) + return -1; + + for (p = buf; p && *p; p++) { + if (!tag && isspace(*p)) + continue; + if (!tag) + tag = p; /* begin of the tag */ + if (*p == ',' || *p == ' ') + end = p; /* terminate the tag */ + else if (*(p + 1) == '\0') + end = p + 1; /* end of optstr */ + if (!tag || !end) + continue; + if (tag >= end) + break; + + *end = '\0'; + + if (*tag == '-') { + tag = tag + 1; + if (strcmp(tag, "unread") == 0) + mutt_set_flag (ctx, hdr, MUTT_READ, 1); + else if (strcmp(tag, "replied") == 0) + mutt_set_flag (ctx, hdr, MUTT_REPLIED, 0); + else if (strcmp(tag, "flagged") == 0) + mutt_set_flag (ctx, hdr, MUTT_FLAG, 0); + } else { + tag = *tag == '+' ? tag + 1 : tag; + if (strcmp(tag, "unread") == 0) + mutt_set_flag (ctx, hdr, MUTT_READ, 0); + else if (strcmp(tag, "replied") == 0) + mutt_set_flag (ctx, hdr, MUTT_REPLIED, 1); + else if (strcmp(tag, "flagged") == 0) + mutt_set_flag (ctx, hdr, MUTT_FLAG, 1); + } + end = tag = NULL; + } + + FREE(&buf); + return 0; +} + int nm_modify_message_tags(CONTEXT *ctx, HEADER *hdr, char *buf) { struct nm_ctxdata *data = get_ctxdata(ctx); @@ -1336,6 +1387,7 @@ int nm_modify_message_tags(CONTEXT *ctx, HEADER *hdr, char *buf) dprint(1, (debugfile, "nm: tags modify: '%s'\n", buf)); update_tags(msg, buf); + update_header_flags(ctx, hdr, buf); update_header_tags(hdr, msg); mutt_set_header_color(ctx, hdr); -- 2.40.0