On Tue, 21 Feb 2012 23:46:34 -0700, Adam Wolfe Gordon <awg+notmuch@xvx.ca> wrote: > This new JSON format for replies includes headers generated for a > reply message as well as the headers of the original message. Using > this data, a client can intelligently create a reply. For example, the > emacs client will be able to create replies with quoted HTML parts by > parsing the HTML parts. > --- > notmuch-client.h | 10 ++++++++-- > notmuch-reply.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ > notmuch-show.c | 30 ++++++++++++++++++++++-------- > test/multipart | 1 - > 4 files changed, 79 insertions(+), 11 deletions(-) > > diff --git a/notmuch-client.h b/notmuch-client.h > index f4a62cc..ef4eaba 100644 > --- a/notmuch-client.h > +++ b/notmuch-client.h > @@ -62,13 +62,13 @@ > #define STRINGIFY(s) STRINGIFY_(s) > #define STRINGIFY_(s) #s > > -struct mime_node; > +typedef struct mime_node mime_node_t; > struct notmuch_show_params; > > typedef struct notmuch_show_format { > const char *message_set_start; > void (*part) (const void *ctx, > - struct mime_node *node, int indent, > + mime_node_t *node, int indent, > const struct notmuch_show_params *params); > const char *message_start; > void (*message) (const void *ctx, > @@ -191,6 +191,12 @@ show_message_body (notmuch_message_t *message, > notmuch_status_t > show_one_part (const char *filename, int part); > > +void > +format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first); > + > +void > +format_headers_json (const void *ctx, GMimeMessage *message, notmuch_bool_t reply); > + > char * > json_quote_chararray (const void *ctx, const char *str, const size_t len); > > diff --git a/notmuch-reply.c b/notmuch-reply.c > index 177e6ca..017c6ae 100644 > --- a/notmuch-reply.c > +++ b/notmuch-reply.c > @@ -601,6 +601,51 @@ notmuch_reply_format_default(void *ctx, > return 0; > } > > +static int > +notmuch_reply_format_json(void *ctx, > + notmuch_config_t *config, > + notmuch_query_t *query, > + notmuch_show_params_t *params, > + notmuch_bool_t reply_all) > +{ > + GMimeMessage *reply; > + notmuch_messages_t *messages; > + notmuch_message_t *message; > + mime_node_t *node; > + > + if (notmuch_query_count_messages (query) != 1) { > + fprintf (stderr, "Error: search term did not match precisely one message.\n"); > + return 1; > + } > + > + messages = notmuch_query_search_messages (query); > + message = notmuch_messages_get (messages); > + if (mime_node_open (ctx, message, params->cryptoctx, params->decrypt, > + &node) != NOTMUCH_STATUS_SUCCESS) > + return 1; > + > + reply = create_reply_message (ctx, config, message, reply_all); > + if (!reply) > + return 1; > + > + /* The headers of the reply message we've created */ > + printf ("{\"reply-headers\": "); > + format_headers_json (ctx, reply, TRUE); > + g_object_unref (G_OBJECT (reply)); > + reply = NULL; > + > + /* Start the original */ > + printf (", \"original\": "); > + > + format_part_json (ctx, node, TRUE); > + > + /* End */ > + printf ("}\n"); > + notmuch_message_destroy (message); > + > + return 0; > +} > + > /* This format is currently tuned for a git send-email --notmuch hook */ > static int > notmuch_reply_format_headers_only(void *ctx, > @@ -663,6 +708,7 @@ notmuch_reply_format_headers_only(void *ctx, > > enum { > FORMAT_DEFAULT, > + FORMAT_JSON, > FORMAT_HEADERS_ONLY, > }; > > @@ -682,6 +728,7 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) > notmuch_opt_desc_t options[] = { > { NOTMUCH_OPT_KEYWORD, &format, "format", 'f', > (notmuch_keyword_t []){ { "default", FORMAT_DEFAULT }, > + { "json", FORMAT_JSON }, > { "headers-only", FORMAT_HEADERS_ONLY }, > { 0, 0 } } }, > { NOTMUCH_OPT_KEYWORD, &reply_all, "reply-to", 'r', > @@ -700,6 +747,8 @@ notmuch_reply_command (void *ctx, int argc, char *argv[]) > > if (format == FORMAT_HEADERS_ONLY) > reply_format_func = notmuch_reply_format_headers_only; > + else if (format == FORMAT_JSON) > + reply_format_func = notmuch_reply_format_json; > else > reply_format_func = notmuch_reply_format_default; > > diff --git a/notmuch-show.c b/notmuch-show.c > index 6a171a4..2126d78 100644 > --- a/notmuch-show.c > +++ b/notmuch-show.c > @@ -290,8 +290,8 @@ format_headers_message_part_text (GMimeMessage *message) > printf ("Date: %s\n", g_mime_message_get_date_as_string (message)); > } > > -static void > -format_headers_json (const void *ctx, GMimeMessage *message) > +void > +format_headers_json (const void *ctx, GMimeMessage *message, notmuch_bool_t reply) > { > void *local = talloc_new (ctx); > InternetAddressList *recipients; > @@ -315,9 +315,23 @@ format_headers_json (const void *ctx, GMimeMessage *message) > printf (", %s: %s", > json_quote_str (local, "Cc"), > json_quote_str (local, recipients_string)); > - printf (", %s: %s}", > - json_quote_str (local, "Date"), > - json_quote_str (local, g_mime_message_get_date_as_string (message))); > + > + if (!reply) > + printf (", %s: %s", > + json_quote_str (local, "Date"), > + json_quote_str (local, g_mime_message_get_date_as_string (message))); > + > + if (reply) { Isn't that an "else"? Otherwise looks good. BR, Jani. > + printf (", %s: %s", > + json_quote_str (local, "In-reply-to"), > + json_quote_str (local, g_mime_object_get_header (GMIME_OBJECT (message), "In-reply-to"))); > + > + printf (", %s: %s", > + json_quote_str (local, "References"), > + json_quote_str (local, g_mime_object_get_header (GMIME_OBJECT (message), "References"))); > + } > + > + printf ("}"); > > talloc_free (local); > } > @@ -652,7 +666,7 @@ format_part_text (const void *ctx, mime_node_t *node, > printf ("\f%s}\n", part_type); > } > > -static void > +void > format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first) > { > /* Any changes to the JSON format should be reflected in the file > @@ -663,7 +677,7 @@ format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first) > format_message_json (ctx, node->envelope_file); > > printf ("\"headers\": "); > - format_headers_json (ctx, GMIME_MESSAGE (node->part)); > + format_headers_json (ctx, GMIME_MESSAGE (node->part), FALSE); > > printf (", \"body\": ["); > format_part_json (ctx, mime_node_child (node, 0), first); > @@ -737,7 +751,7 @@ format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first) > } else if (GMIME_IS_MESSAGE (node->part)) { > printf (", \"content\": [{"); > printf ("\"headers\": "); > - format_headers_json (local, GMIME_MESSAGE (node->part)); > + format_headers_json (local, GMIME_MESSAGE (node->part), FALSE); > > printf (", \"body\": ["); > terminator = "]}]"; > diff --git a/test/multipart b/test/multipart > index f102294..e7abcc2 100755 > --- a/test/multipart > +++ b/test/multipart > @@ -590,7 +590,6 @@ EOF > test_expect_equal_file OUTPUT EXPECTED > > test_begin_subtest "'notmuch reply' to a multipart message with json format" > -test_subtest_known_broken > notmuch reply --format=json 'id:87liy5ap00.fsf@yoom.home.cworth.org' | notmuch_json_show_sanitize >OUTPUT > cat <<EOF >EXPECTED > {"reply-headers": {"Subject": "Re: Multipart message", > -- > 1.7.5.4 > > _______________________________________________ > notmuch mailing list > notmuch@notmuchmail.org > http://notmuchmail.org/mailman/listinfo/notmuch