[PATCH v7 04/10] reply: Add a JSON reply format.
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 | 14 ++ notmuch-reply.c | 49 + notmuch-show.c | 29 + test/multipart |1 - 4 files changed, 80 insertions(+), 13 deletions(-) diff --git a/notmuch-client.h b/notmuch-client.h index f4a62cc..270daff 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); @@ -288,7 +294,7 @@ debugger_is_active (void); * parts. Message-type parts have one child, multipart-type parts * have multiple children, and leaf parts have zero children. */ -typedef struct mime_node { +struct mime_node { /* The MIME object of this part. This will be a GMimeMessage, * GMimePart, GMimeMultipart, or a subclass of one of these. * @@ -351,7 +357,7 @@ typedef struct mime_node { * number to assign it (or -1 if unknown). */ int next_child; int next_part_num; -} mime_node_t; +}; /* Construct a new MIME node pointing to the root message part of * message. If cryptoctx is non-NULL, it will be used to verify diff --git a/notmuch-reply.c b/notmuch-reply.c index f1478cc..e2b6c25 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -604,6 +604,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, @@ -666,6 +711,7 @@ notmuch_reply_format_headers_only(void *ctx, enum { FORMAT_DEFAULT, +FORMAT_JSON, FORMAT_HEADERS_ONLY, }; @@ -685,6 +731,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', @@ -703,6 +750,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 05d51b2..cb3a427 100644 --- a/notmuch-show.c +++ b/notmuch-s
[PATCH v7 04/10] reply: Add a JSON reply format.
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 | 14 ++ notmuch-reply.c | 49 + notmuch-show.c | 29 + test/multipart |1 - 4 files changed, 80 insertions(+), 13 deletions(-) diff --git a/notmuch-client.h b/notmuch-client.h index f4a62cc..270daff 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); @@ -288,7 +294,7 @@ debugger_is_active (void); * parts. Message-type parts have one child, multipart-type parts * have multiple children, and leaf parts have zero children. */ -typedef struct mime_node { +struct mime_node { /* The MIME object of this part. This will be a GMimeMessage, * GMimePart, GMimeMultipart, or a subclass of one of these. * @@ -351,7 +357,7 @@ typedef struct mime_node { * number to assign it (or -1 if unknown). */ int next_child; int next_part_num; -} mime_node_t; +}; /* Construct a new MIME node pointing to the root message part of * message. If cryptoctx is non-NULL, it will be used to verify diff --git a/notmuch-reply.c b/notmuch-reply.c index f1478cc..e2b6c25 100644 --- a/notmuch-reply.c +++ b/notmuch-reply.c @@ -604,6 +604,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, @@ -666,6 +711,7 @@ notmuch_reply_format_headers_only(void *ctx, enum { FORMAT_DEFAULT, +FORMAT_JSON, FORMAT_HEADERS_ONLY, }; @@ -685,6 +731,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', @@ -703,6 +750,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 05d51b2..cb3a427 100644 --- a/notmuch-show.c +++ b