]> granicus.if.org Git - neomutt/commitdiff
add modify-label
authorKarel Zak <kzak@redhat.com>
Thu, 15 Dec 2011 00:14:03 +0000 (01:14 +0100)
committerRichard Russon <rich@flatcap.org>
Mon, 14 Mar 2016 23:11:40 +0000 (23:11 +0000)
Signed-off-by: Karel Zak <kzak@redhat.com>
OPS.NOTMUCH
curs_main.c
functions.h
mutt_notmuch.c
mutt_notmuch.h

index eca66ac25df807c3a66cc2347bdb46c640678636..21b611dfae14513c41d5f483f2e209aa94fe59d5 100644 (file)
@@ -1,2 +1,3 @@
 OP_MAIN_CHANGE_VFOLDER "open a different virtual folder"
 OP_MAIN_VFOLDER_FROM_QUERY "generate virtual folder from query"
+OP_MAIN_MODIFY_LABELS "modify (notmuch) tags"
index 510e360b413be02ce6d6e37399c17c376e21ce20..8e1835596c29bdc5434bfb3c3c3c9caff1fd3118 100644 (file)
@@ -1381,8 +1381,64 @@ int mutt_index_menu (void)
        break;
 
 #ifdef USE_NOTMUCH
-      case OP_MAIN_VFOLDER_FROM_QUERY:
+      case OP_MAIN_MODIFY_LABELS:
+       if (Context->magic != M_NOTMUCH) {
+         mutt_message _("No virtual folder, aborting.");
+         break;
+       }
+       CHECK_MSGCOUNT;
+        CHECK_VISIBLE;
+       buf[0] = '\0';
+        if (mutt_get_field ("Add/remove labels: ", buf, sizeof (buf), 0) != 0 || !buf[0])
+        {
+          mutt_message _("No labels, aborting.");
+          break;
+        }
+       if (tag && !option (OPTAUTOTAG))
+       {
+         char msgbuf[STRING];
+         progress_t progress;
+         int px;
+
+         if (!Context->quiet) {
+           snprintf(msgbuf, sizeof (msgbuf), _("Update labels..."));
+           mutt_progress_init(&progress, msgbuf, M_PROGRESS_MSG,
+                                  1, Context->tagged);
+         }
+         nm_longrun_init(Context, TRUE);
+         for (px = 0, j = 0; j < Context->vcount; j++) {
+           if (Context->hdrs[Context->v2r[j]]->tagged) {
+             if (!Context->quiet)
+               mutt_progress_update(&progress, ++px, -1);
+             nm_modify_message_tags(Context, Context->hdrs[Context->v2r[j]], buf, sizeof (buf));
+           }
+         }
+         nm_longrun_done(Context);
+         menu->redraw = REDRAW_STATUS | REDRAW_INDEX;
+       }
+       else
+       {
+         if (nm_modify_message_tags(Context, CURHDR, buf, sizeof (buf))) {
+           mutt_message _("Failed to modify labels, aborting.");
+           break;
+         }
+         if (option (OPTRESOLVE))
+         {
+           if ((menu->current = ci_next_undeleted (menu->current)) == -1)
+           {
+             menu->current = menu->oldcurrent;
+             menu->redraw = REDRAW_CURRENT;
+           }
+           else
+             menu->redraw = REDRAW_MOTION_RESYNCH;
+         }
+         else
+           menu->redraw = REDRAW_CURRENT;
+       }
+       menu->redraw |= REDRAW_STATUS;
+       break;
 
+      case OP_MAIN_VFOLDER_FROM_QUERY:
        buf[0] = '\0';
         if (mutt_get_field ("Query: ", buf, sizeof (buf), 0) != 0 || !buf[0])
         {
index 28cc93edc11b578fb9560c1add2afdc3b5c25e3a..be524c23e1ee59c11f2dbc9284efde84e77af9a0 100644 (file)
@@ -183,6 +183,7 @@ const struct binding_t OpMain[] = { /* map: index */
 #ifdef USE_NOTMUCH
   { "change-vfolder",          OP_MAIN_CHANGE_VFOLDER,         "X" },
   { "vfolder-from-query",      OP_MAIN_VFOLDER_FROM_QUERY,     "\033X" },
+  { "modify-labels",           OP_MAIN_MODIFY_LABELS,          "`" },
 #endif
   { NULL,                      0,                              NULL }
 };
@@ -302,6 +303,7 @@ const struct binding_t OpPager[] = { /* map: pager */
 #ifdef USE_NOTMUCH
   { "change-vfolder",          OP_MAIN_CHANGE_VFOLDER,         "X" },
   { "vfolder-from-query",      OP_MAIN_VFOLDER_FROM_QUERY,     "\033X" },
+  { "modify-labels",           OP_MAIN_MODIFY_LABELS,          "`" },
 #endif
 
   { NULL,              0,                              NULL }
index a0198b7ee8829c9bb6e272de320cc11be3cd24b1..3e8c5cdab27b9adc1facb2ca9dad7eb2377b60dc 100644 (file)
@@ -48,6 +48,7 @@ struct uri_tag {
 struct nm_hdrdata {
        char *folder;
        char *tags;
+       char *id;       /* notmuch message ID */
        int magic;
 };
 
@@ -60,6 +61,7 @@ struct nm_data {
        char *db_filename;
        char *db_query;
        int db_limit;
+       int longrun;
 
        struct uri_tag *query_items;
 };
@@ -157,6 +159,7 @@ static void free_hdrdata(HEADER *h)
        if (data) {
                FREE(&data->folder);
                FREE(&data->tags);
+               FREE(&data->id);
                FREE(&data);
        }
        h->data = NULL;
@@ -202,6 +205,12 @@ int nm_header_get_magic(HEADER *h)
        return h && h->data ? ((struct nm_hdrdata *) h->data)->magic : 0;
 }
 
+static const char *nm_header_get_id(HEADER *h)
+{
+       return h && h->data ? ((struct nm_hdrdata *) h->data)->id : NULL;
+}
+
+
 char *nm_header_get_fullpath(HEADER *h, char *buf, size_t bufsz)
 {
        snprintf(buf, bufsz, "%s/%s", nm_header_get_folder(h), h->path);
@@ -231,6 +240,8 @@ static int init_data(CONTEXT *ctx)
 
 static struct nm_data *get_data(CONTEXT *ctx)
 {
+       if (ctx->magic != M_NOTMUCH)
+               return NULL;
        return ctx->data;
 }
 
@@ -293,26 +304,38 @@ static void release_db(CONTEXT *ctx)
        }
 }
 
-static struct nm_hdrdata *create_hdrdata(HEADER *h, const char *path,
-                                             notmuch_message_t *msg)
+void nm_longrun_init(CONTEXT *ctx, int writable)
 {
-       struct nm_hdrdata *data =
-                       safe_calloc(1, sizeof(struct nm_hdrdata));
-       notmuch_tags_t *tags;
-       char *tstr = NULL;
-       size_t sz = 0;
-       char *p;
+       struct nm_data *data = get_data(ctx);
 
-       p = strrchr(path, '/');
-       if (p && p - path > 3 &&
-           (strncmp(p - 3, "cur", 3) == 0 ||
-            strncmp(p - 3, "new", 3) == 0 ||
-            strncmp(p - 3, "tmp", 3) == 0)) {
-                       data->magic = M_MAILDIR;
-                       p -= 3;
-                       h->path = safe_strdup(p);
-                       data->folder = strndup(path, p - path - 1);
+       if (data) {
+               get_db(ctx, writable);
+               data->longrun = TRUE;
        }
+}
+
+void nm_longrun_done(CONTEXT *ctx)
+{
+       struct nm_data *data = get_data(ctx);
+
+       if (data) {
+               release_db(ctx);
+               data->longrun = FALSE;
+       }
+}
+
+static int is_longrun(CONTEXT *ctx)
+{
+       struct nm_data *data = get_data(ctx);
+
+       return data && data->longrun;
+}
+
+static int init_message_tags(struct nm_hdrdata *data, notmuch_message_t *msg)
+{
+       notmuch_tags_t *tags;
+       char *tstr = NULL, *p;
+       size_t sz = 0;
 
        for (tags = notmuch_message_get_tags(msg);
             tags && notmuch_tags_valid(tags);
@@ -346,8 +369,37 @@ static struct nm_hdrdata *create_hdrdata(HEADER *h, const char *path,
                sz += xsz;
        }
 
+       FREE(&data->tags);
        data->tags = tstr;
+       return 0;
+}
+
+static struct nm_hdrdata *create_hdrdata(HEADER *h, const char *path,
+                                             notmuch_message_t *msg)
+{
+       struct nm_hdrdata *data =
+                       safe_calloc(1, sizeof(struct nm_hdrdata));
+       const char *id;
+       char *p;
+
+       p = strrchr(path, '/');
+       if (p && p - path > 3 &&
+           (strncmp(p - 3, "cur", 3) == 0 ||
+            strncmp(p - 3, "new", 3) == 0 ||
+            strncmp(p - 3, "tmp", 3) == 0)) {
+                       data->magic = M_MAILDIR;
+                       p -= 3;
+                       h->path = safe_strdup(p);
+                       data->folder = strndup(path, p - path - 1);
+       }
+
+       id = notmuch_message_get_message_id(msg);
+       if (id)
+               data->id = safe_strdup(id);
+
        h->data = data;
+       init_message_tags(data, msg);
+
        return data;
 }
 
@@ -396,6 +448,8 @@ int nm_read_query(CONTEXT *ctx)
                ctx->size += h->content->length;
                ctx->hdrs[ctx->msgcount] = h;
                ctx->msgcount++;
+
+               notmuch_message_destroy(m);
        }
 
        notmuch_query_destroy(q);
@@ -421,6 +475,66 @@ char *nm_uri_from_query(CONTEXT *ctx, char *buf, size_t bufsz)
        return buf;
 }
 
+static notmuch_message_t *get_message(notmuch_database_t *db, HEADER *hdr)
+{
+       const char *id = nm_header_get_id(hdr);
+       return id && db ? notmuch_database_find_message(db, id) :  NULL;
+}
+
+int nm_modify_message_tags(CONTEXT *ctx, HEADER *hdr, char *buf, size_t bufsz)
+{
+       notmuch_database_t *db = NULL;
+       notmuch_message_t *msg = NULL;
+       int rc = -1;
+       char *tag = NULL, *end = NULL, *p;
+
+       if (!buf || !*buf || !ctx
+              || ctx->magic != M_NOTMUCH
+              || !(db = get_db(ctx, TRUE))
+              || !(msg = get_message(db, hdr)))
+               goto done;
+
+       buf = safe_strdup(buf);
+
+       notmuch_message_freeze(msg);
+
+       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 == '-')
+                       notmuch_message_remove_tag(msg, tag + 1);
+               else
+                       notmuch_message_add_tag(msg, *tag == '+' ? tag + 1 : tag);
+               end = tag = NULL;
+       }
+
+       notmuch_message_thaw(msg);
+
+       init_message_tags(hdr->data, msg);
+
+       rc = 0;
+done:
+       FREE(&buf);
+       if (msg)
+               notmuch_message_destroy(msg);
+       if (!is_longrun(ctx) && db)
+               release_db(ctx);
+       return rc;
+}
+
 static int _nm_update_filename(notmuch_database_t *db,
                        const char *old, const char *new)
 {
@@ -496,7 +610,7 @@ int nm_sync(CONTEXT *ctx, int *index_hint)
 
                        if (h->deleted)
                                notmuch_database_remove_message(db, old);
-                       else if (new && old)
+                       else if (*new && *old)
                                _nm_update_filename(db, old, new);
                }
        }
index d25f6a29d26295c8e7098cc62322c1adb1eb7c33..c2080d622c60dc38ef8afd233531538776791be6 100644 (file)
@@ -14,5 +14,9 @@ char *nm_header_get_tags(HEADER *h);
 int nm_get_count(char *path, unsigned *all, unsigned *new);
 int nm_update_filename(CONTEXT *ctx, const char *old, const char *new);
 char *nm_uri_from_query(CONTEXT *ctx, char *buf, size_t bufsz);
+int nm_modify_message_tags(CONTEXT *ctx, HEADER *hdr, char *buf, size_t bufsz);
+
+void nm_longrun_init(CONTEXT *cxt, int writable);
+void nm_longrun_done(CONTEXT *cxt);
 
 #endif /* _MUTT_NOTMUCH_H_ */