--- /dev/null
+Return-Path: <amthrax@drake.mit.edu>\r
+X-Original-To: notmuch@notmuchmail.org\r
+Delivered-To: notmuch@notmuchmail.org\r
+Received: from localhost (localhost [127.0.0.1])\r
+ by olra.theworths.org (Postfix) with ESMTP id DD13B431FC2\r
+ for <notmuch@notmuchmail.org>; Sun, 19 Feb 2012 16:26:39 -0800 (PST)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: -0.7\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5\r
+ tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\r
+Received: from olra.theworths.org ([127.0.0.1])\r
+ by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
+ with ESMTP id SQ85omdwlsoP for <notmuch@notmuchmail.org>;\r
+ Sun, 19 Feb 2012 16:26:37 -0800 (PST)\r
+Received: from dmz-mailsec-scanner-1.mit.edu (DMZ-MAILSEC-SCANNER-1.MIT.EDU\r
+ [18.9.25.12])\r
+ by olra.theworths.org (Postfix) with ESMTP id 59B33431FC0\r
+ for <notmuch@notmuchmail.org>; Sun, 19 Feb 2012 16:26:36 -0800 (PST)\r
+X-AuditID: 1209190c-b7fad6d000000920-ee-4f41933b7b1a\r
+Received: from mailhub-auth-1.mit.edu ( [18.9.21.35])\r
+ by dmz-mailsec-scanner-1.mit.edu (Symantec Messaging Gateway) with SMTP\r
+ id BE.CF.02336.B33914F4; Sun, 19 Feb 2012 19:26:35 -0500 (EST)\r
+Received: from outgoing.mit.edu (OUTGOING-AUTH.MIT.EDU [18.7.22.103])\r
+ by mailhub-auth-1.mit.edu (8.13.8/8.9.2) with ESMTP id q1K0QZLd016444; \r
+ Sun, 19 Feb 2012 19:26:35 -0500\r
+Received: from drake.mit.edu\r
+ (209-6-116-242.c3-0.arl-ubr1.sbo-arl.ma.cable.rcn.com\r
+ [209.6.116.242]) (authenticated bits=0)\r
+ (User authenticated as amdragon@ATHENA.MIT.EDU)\r
+ by outgoing.mit.edu (8.13.6/8.12.4) with ESMTP id q1K0QX8V000298\r
+ (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NOT);\r
+ Sun, 19 Feb 2012 19:26:34 -0500 (EST)\r
+Received: from amthrax by drake.mit.edu with local (Exim 4.77)\r
+ (envelope-from <amthrax@drake.mit.edu>)\r
+ id 1RzH5N-0001yC-8V; Sun, 19 Feb 2012 19:26:33 -0500\r
+From: Austin Clements <amdragon@MIT.EDU>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH v2 1/8] Document the JSON schemata used by show and search\r
+Date: Sun, 19 Feb 2012 19:26:23 -0500\r
+Message-Id: <1329697590-7404-2-git-send-email-amdragon@mit.edu>\r
+X-Mailer: git-send-email 1.7.7.3\r
+In-Reply-To: <1329697590-7404-1-git-send-email-amdragon@mit.edu>\r
+References: <1329240823-7856-1-git-send-email-amdragon@mit.edu>\r
+ <1329697590-7404-1-git-send-email-amdragon@mit.edu>\r
+X-Brightmail-Tracker:\r
+ H4sIAAAAAAAAA+NgFtrDIsWRmVeSWpSXmKPExsUixCmqrGs92dHf4GSvocX1mzOZLd6snMfq\r
+ wORx+OtCFo9nq24xBzBFcdmkpOZklqUW6dslcGXs3rWfqWCFZsWGJW3MDYyL5LoYOTkkBEwk\r
+ /v1cyghhi0lcuLeerYuRi0NIYB+jxOX2u8wQzgZGiXPvWqGc+0wSXx/8Y4Rw5jNKLNsxhQWk\r
+ n01AQ2Lb/uVgs0QEpCV23p3NCmIzC1hJHL66CcwWFvCSmHlkOtAODg4WAVWJ1f06IGFeAXuJ\r
+ 06d+Q52hIHFu9Tl2kBJOAQeJ1TtcQcJCAqUSR55sYZrAyL+AkWEVo2xKbpVubmJmTnFqsm5x\r
+ cmJeXmqRrqFebmaJXmpK6SZGcCBJ8uxgfHNQ6RCjAAejEg+vVJmDvxBrYllxZe4hRkkOJiVR\r
+ 3nWTHP2F+JLyUyozEosz4otKc1KLDzFKcDArifAusAfK8aYkVlalFuXDpKQ5WJTEeVW03vkJ\r
+ CaQnlqRmp6YWpBbBZGU4OJQkeHeBDBUsSk1PrUjLzClBSDNxcIIM5wEaPhukhre4IDG3ODMd\r
+ In+KUVFKnLceJCEAksgozYPrhUX6K0ZxoFeEeVeAVPEAkwRc9yugwUxAg3mF7EAGlyQipKQa\r
+ GNu/b7WzTF33aH9Y3fWGnyJK1ebvyrqebQ7cb5TI9/p/xbK5O1Iv6M4qPsYsd2Nqi/D5eTdb\r
+ sqTXyj08461lNo/73G7B7BsnzXp7Jbdee/Ph820D4a5nXs0PlvkeEJhRe3faD21/y8+FX2OL\r
+ DRbwuc144LVHYmNAV0vd5QiRjTy6Eo1X9RVaM5VYijMSDbWYi4oTAekS3ijPAgAA\r
+Cc: tomi.ollila@iki.fi\r
+X-BeenThere: notmuch@notmuchmail.org\r
+X-Mailman-Version: 2.1.13\r
+Precedence: list\r
+List-Id: "Use and development of the notmuch mail system."\r
+ <notmuch.notmuchmail.org>\r
+List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
+List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
+List-Post: <mailto:notmuch@notmuchmail.org>\r
+List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
+List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
+ <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
+X-List-Received-Date: Mon, 20 Feb 2012 00:26:40 -0000\r
+\r
+---\r
+ devel/schemata | 138 ++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+ notmuch-search.c | 3 +\r
+ notmuch-show.c | 2 +\r
+ 3 files changed, 143 insertions(+), 0 deletions(-)\r
+ create mode 100644 devel/schemata\r
+\r
+diff --git a/devel/schemata b/devel/schemata\r
+new file mode 100644\r
+index 0000000..24ad775\r
+--- /dev/null\r
++++ b/devel/schemata\r
+@@ -0,0 +1,138 @@\r
++This file describes the schemata used for notmuch's structured output\r
++format (currently JSON).\r
++\r
++[]'s indicate lists. List items can be marked with a '?', meaning\r
++they are optional; or a '*', meaning there can be zero or more of that\r
++item. {}'s indicate an object that maps from field identifiers to\r
++values. An object field marked '?' is optional. |'s indicate\r
++alternates (e.g., int|string means something can be an int or a\r
++string).\r
++\r
++Common non-terminals\r
++--------------------\r
++\r
++# Number of seconds since the Epoch\r
++unix_time = int\r
++\r
++# Thread ID, sans "thread:"\r
++threadid = string\r
++\r
++# Message ID, sans "id:"\r
++messageid = string\r
++\r
++notmuch show schema\r
++-------------------\r
++\r
++# A top-level set of threads (do_show)\r
++# Returned by notmuch show without a --part argument\r
++thread_set = [thread*]\r
++\r
++# Top-level messages in a thread (show_messages)\r
++thread = [thread_node*]\r
++\r
++# A message and its replies (show_messages)\r
++thread_node = [\r
++ message?, # present if --entire-thread or matched\r
++ [thread_node*] # children of message\r
++]\r
++\r
++# A message (show_message)\r
++message = {\r
++ # (format_message_json)\r
++ id: messageid,\r
++ match: bool,\r
++ filename: string,\r
++ timestamp: unix_time, # date header as unix time\r
++ date_relative: string, # user-friendly timestamp\r
++ tags: [string*],\r
++\r
++ headers: headers,\r
++ body: [part]\r
++}\r
++\r
++# A MIME part (show_message_body)\r
++part = {\r
++ # format_part_start_json\r
++ id: int|string, # part id (currently DFS part number)\r
++\r
++ # format_part_encstatus_json\r
++ encstatus?: encstatus,\r
++\r
++ # format_part_sigstatus_json\r
++ sigstatus?: sigstatus,\r
++\r
++ # format_part_content_json\r
++ content-type: string,\r
++ content-id?: string,\r
++ # if content-type starts with "multipart/":\r
++ content: [part*],\r
++ # if content-type is "message/rfc822":\r
++ content: [{headers: headers, body: [part]}],\r
++ # otherwise (leaf parts):\r
++ filename?: string,\r
++ content-charset?: string,\r
++ # A leaf part's body content is optional, but may be included if\r
++ # it can be correctly encoded as a string. Consumers should use\r
++ # this in preference to fetching the part content separately.\r
++ content?: string\r
++}\r
++\r
++# The headers of a message (format_headers_json with raw headers) or\r
++# a part (format_headers_message_part_json with pretty-printed headers)\r
++headers = {\r
++ Subject: string,\r
++ From: string,\r
++ To?: string,\r
++ Cc?: string,\r
++ Bcc?: string,\r
++ Date: string\r
++}\r
++\r
++# Encryption status (format_part_encstatus_json)\r
++encstatus = [{status: "good"|"bad"}]\r
++\r
++# Signature status (format_part_sigstatus_json)\r
++sigstatus = [signature*]\r
++\r
++signature = {\r
++ # signature_status_to_string\r
++ status: "none"|"good"|"bad"|"error"|"unknown",\r
++ # if status is "good":\r
++ fingerprint?: string,\r
++ created?: unix_time,\r
++ expires?: unix_time,\r
++ userid?: string\r
++ # if status is not "good":\r
++ keyid?: string\r
++ # if the signature has errors:\r
++ errors?: int\r
++}\r
++\r
++notmuch search schema\r
++---------------------\r
++\r
++# --output=summary\r
++summary = [thread*]\r
++\r
++# --output=threads\r
++threads = [threadid*]\r
++\r
++# --output=messages\r
++messages = [messageid*]\r
++\r
++# --output=files\r
++files = [string*]\r
++\r
++# --output=tags\r
++tags = [string*]\r
++\r
++thread = {\r
++ thread: threadid,\r
++ timestamp: unix_time,\r
++ date_relative: string, # user-friendly timestamp\r
++ matched: int, # number of matched messages\r
++ total: int, # total messages in thread\r
++ authors: string, # comma-separated names with | between\r
++ # matched and unmatched\r
++ subject: string\r
++}\r
+diff --git a/notmuch-search.c b/notmuch-search.c\r
+index d504051..92ce38a 100644\r
+--- a/notmuch-search.c\r
++++ b/notmuch-search.c\r
+@@ -90,6 +90,9 @@ format_thread_json (const void *ctx,\r
+ const int total,\r
+ const char *authors,\r
+ const char *subject);\r
++\r
++/* Any changes to the JSON format should be reflected in the file\r
++ * devel/schemata. */\r
+ static const search_format_t format_json = {\r
+ "[",\r
+ "{",\r
+diff --git a/notmuch-show.c b/notmuch-show.c\r
+index d930f94..93fb16f 100644\r
+--- a/notmuch-show.c\r
++++ b/notmuch-show.c\r
+@@ -65,6 +65,8 @@ format_part_content_json (GMimeObject *part);\r
+ static void\r
+ format_part_end_json (GMimeObject *part);\r
+ \r
++/* Any changes to the JSON format should be reflected in the file\r
++ * devel/schemata. */\r
+ static const notmuch_show_format_t format_json = {\r
+ "[", NULL,\r
+ "{", format_message_json,\r
+-- \r
+1.7.7.3\r
+\r