From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from localhost (localhost [127.0.0.1]) by olra.theworths.org (Postfix) with ESMTP id 26A37431FC3 for ; Fri, 9 Mar 2012 15:09:08 -0800 (PST) X-Virus-Scanned: Debian amavisd-new at olra.theworths.org X-Spam-Flag: NO X-Spam-Score: -0.7 X-Spam-Level: X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5 tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled Received: from olra.theworths.org ([127.0.0.1]) by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id VjsFzxUkPuvS for ; Fri, 9 Mar 2012 15:09:04 -0800 (PST) Received: from mail-lpp01m010-f53.google.com (mail-lpp01m010-f53.google.com [209.85.215.53]) (using TLSv1 with cipher RC4-SHA (128/128 bits)) (No client certificate requested) by olra.theworths.org (Postfix) with ESMTPS id DDDE5431FAE for ; Fri, 9 Mar 2012 15:09:03 -0800 (PST) Received: by lahc1 with SMTP id c1so2275980lah.26 for ; Fri, 09 Mar 2012 15:09:02 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20120113; h=from:to:subject:in-reply-to:references:user-agent:date:message-id :mime-version:content-type:x-gm-message-state; bh=iGTAKEuykInJLscHrAgJXloAni6J/gmB/gjImATZpZc=; b=nI70bU5msarKhwpXMzp6etG9VGc6ImnR3KqQEX+h8bFhoqGH9m1ilve/bC+dSmnWlo QHXSIw3Vasu79zO1HXNQsJ/hY9usNeWPeFuoHuMh9vZspvqajdT3rmaOg+HPOGlARTPs 9lkKF9dy0EA01Hzn5aDizucp7yFfH37ki3EfoU5Av6aw/iFFCWzGWOITig2hTlp29a8e nHGkOe0Mq4q7J9y74E/2qjrs1lTqNuvpB4O/OAZnvAKPIKG+0LKUklUG4nLDtgc6u+kg uLYhtR8Q7B1TyhIa5VfbGiAbdKIetlV2DATE3CBERcpJkDg1wwcHXDllkZ2WXq/QlXkO Wlkg== Received: by 10.112.38.3 with SMTP id c3mr1445266lbk.94.1331334542180; Fri, 09 Mar 2012 15:09:02 -0800 (PST) Received: from localhost (dsl-hkibrasgw4-fe50f800-253.dhcp.inet.fi. [84.248.80.253]) by mx.google.com with ESMTPS id nh5sm5972532lab.5.2012.03.09.15.08.59 (version=SSLv3 cipher=OTHER); Fri, 09 Mar 2012 15:09:00 -0800 (PST) From: Jani Nikula To: Adam Wolfe Gordon , notmuch@notmuchmail.org Subject: Re: [PATCH v6 05/10] reply: Add a JSON reply format. In-Reply-To: <1329893199-21630-6-git-send-email-awg+notmuch@xvx.ca> References: <1329893199-21630-1-git-send-email-awg+notmuch@xvx.ca> <1329893199-21630-6-git-send-email-awg+notmuch@xvx.ca> User-Agent: Notmuch/0.11.1+295~g780f284 (http://notmuchmail.org) Emacs/23.3.1 (i686-pc-linux-gnu) Date: Sat, 10 Mar 2012 01:08:58 +0200 Message-ID: <87d38l8j91.fsf@nikula.org> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii X-Gm-Message-State: ALoCoQkAIH0T9yfAEPf7yqPlYWQ2M4KDGiS0tBACl6rntLAEQgeHqpc+r6STfHpkD56mHE0tRA+Y X-BeenThere: notmuch@notmuchmail.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: "Use and development of the notmuch mail system." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 09 Mar 2012 23:09:08 -0000 On Tue, 21 Feb 2012 23:46:34 -0700, Adam Wolfe Gordon 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 <EXPECTED > {"reply-headers": {"Subject": "Re: Multipart message", > -- > 1.7.5.4 > > _______________________________________________ > notmuch mailing list > notmuch@notmuchmail.org > http://notmuchmail.org/mailman/listinfo/notmuch