[PATCH v6 1/3] Add support for structured output formatters.
authorcraven <craven@gmx.net>
Mon, 16 Jul 2012 08:35:00 +0000 (10:35 +0200)
committerW. Trevor King <wking@tremily.us>
Fri, 7 Nov 2014 17:48:21 +0000 (09:48 -0800)
02/1d460ed2a2f34b2e9ff08e52b836162c43c1de [new file with mode: 0644]

diff --git a/02/1d460ed2a2f34b2e9ff08e52b836162c43c1de b/02/1d460ed2a2f34b2e9ff08e52b836162c43c1de
new file mode 100644 (file)
index 0000000..7a1f687
--- /dev/null
@@ -0,0 +1,206 @@
+Return-Path: <craven@gmx.net>\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 7C286431FC3\r
+       for <notmuch@notmuchmail.org>; Mon, 16 Jul 2012 23:04:43 -0700 (PDT)\r
+X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
+X-Spam-Flag: NO\r
+X-Spam-Score: 0.001\r
+X-Spam-Level: \r
+X-Spam-Status: No, score=0.001 tagged_above=-999 required=5\r
+       tests=[FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001]\r
+       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 40t7iUMC0gG7 for <notmuch@notmuchmail.org>;\r
+       Mon, 16 Jul 2012 23:04:41 -0700 (PDT)\r
+Received: from mailout-de.gmx.net (mailout-de.gmx.net [213.165.64.22])\r
+       by olra.theworths.org (Postfix) with SMTP id 9690E431FDA\r
+       for <notmuch@notmuchmail.org>; Mon, 16 Jul 2012 23:04:38 -0700 (PDT)\r
+Received: (qmail invoked by alias); 17 Jul 2012 06:04:36 -0000\r
+Received: from gw.arelion.cust.net.lagis.at (EHLO dodekanex.arelion.at)\r
+       [83.164.197.182]\r
+       by mail.gmx.net (mp032) with SMTP; 17 Jul 2012 08:04:36 +0200\r
+X-Authenticated: #201305\r
+X-Provags-ID: V01U2FsdGVkX1+GX8Zf46mGH4YAZBhReaiFebarWJ1/Yk5o3h7s5/\r
+       i5mbwX5C2lkeB0\r
+Received: by dodekanex.arelion.at (Postfix, from userid 1000)\r
+       id EB349303543; Mon, 16 Jul 2012 10:35:05 +0200 (CEST)\r
+From: <craven@gmx.net>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH v6 1/3] Add support for structured output formatters.\r
+Date: Mon, 16 Jul 2012 10:35:00 +0200\r
+Message-Id: <1342427702-23316-2-git-send-email-craven@gmx.net>\r
+X-Mailer: git-send-email 1.7.11.1\r
+In-Reply-To: <1342427702-23316-1-git-send-email-craven@gmx.net>\r
+References: <20120714020954.GD31670@mit.edu>\r
+       <1342427702-23316-1-git-send-email-craven@gmx.net>\r
+X-Y-GMX-Trusted: 0\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: Tue, 17 Jul 2012 06:04:44 -0000\r
+\r
+This patch adds a new struct type sprinter_t, which is used for\r
+structured formatting, e.g. JSON or S-Expressions. The structure printer\r
+is heavily based on code from Austin Clements\r
+(id:87d34hsdx8.fsf@awakening.csail.mit.edu).\r
+\r
+It includes the following functions:\r
+\r
+    /* Start a new map/dictionary structure. This should be followed by\r
+     * a sequence of alternating calls to map_key and one of the\r
+     * value-printing functions until the map is ended by end.\r
+     */\r
+    void (*begin_map) (struct sprinter *);\r
+\r
+    /* Start a new list/array structure.\r
+     */\r
+    void (*begin_list) (struct sprinter *);\r
+\r
+    /* End the last opened list or map structure.\r
+     */\r
+    void (*end) (struct sprinter *);\r
+\r
+    /* Print one string/integer/boolean/null element (possibly inside a\r
+     * list or map, followed or preceded by separators).\r
+     * For string, the char * must be UTF-8 encoded.\r
+     */\r
+    void (*string) (struct sprinter *, const char *);\r
+    void (*integer) (struct sprinter *, int);\r
+    void (*boolean) (struct sprinter *, notmuch_bool_t);\r
+    void (*null) (struct sprinter *);\r
+\r
+    /* Print the key of a map's key/value pair. The char * must be UTF-8\r
+     * encoded.\r
+     */\r
+    void (*map_key) (struct sprinter *, const char *);\r
+\r
+    /* Insert a separator (usually extra whitespace) for improved\r
+     * readability without affecting the abstract syntax of the\r
+     * structure being printed.\r
+     * For JSON, this could simply be a line break.\r
+     */\r
+    void (*separator) (struct sprinter *);\r
+\r
+To support the plain text format properly, the following two additional\r
+functions must also be implemented:\r
+\r
+    /* Set the current string prefix. This only affects the text\r
+     * printer, which will print this string, followed by a colon,\r
+     * before any string. For other printers, this does nothing.\r
+     */\r
+    void (*set_prefix) (struct sprinter *, const char *);\r
+\r
+    /* Return TRUE if this is a text printer. Some special casing\r
+     * applies to the pure plain text printer. This should always\r
+     * return FALSE in custom structured output printers.\r
+     */\r
+    notmuch_bool_t (*is_text_printer) (struct sprinter *);\r
+\r
+The printer can (and should) use internal state to insert delimiters\r
+and syntax at the correct places.\r
+\r
+Example:\r
+\r
+format->begin_map(format);\r
+format->map_key(format, "foo");\r
+format->begin_list(format);\r
+format->integer(format, 1);\r
+format->integer(format, 2);\r
+format->integer(format, 3);\r
+format->end(format);\r
+format->map_key(format, "bar");\r
+format->begin_map(format);\r
+format->map_key(format, "baaz");\r
+format->string(format, "hello world");\r
+format->end(format);\r
+format->end(format);\r
+\r
+would output JSON as follows:\r
+\r
+{"foo": [1, 2, 3], "bar": { "baaz": "hello world"}}\r
+---\r
+ sprinter.h | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
+ 1 file changed, 60 insertions(+)\r
+ create mode 100644 sprinter.h\r
+\r
+diff --git a/sprinter.h b/sprinter.h\r
+new file mode 100644\r
+index 0000000..dc09a15\r
+--- /dev/null\r
++++ b/sprinter.h\r
+@@ -0,0 +1,60 @@\r
++#ifndef NOTMUCH_SPRINTER_H\r
++#define NOTMUCH_SPRINTER_H\r
++\r
++/* Necessary for notmuch_bool_t */\r
++#include "notmuch-client.h"\r
++\r
++/* Structure printer interface. This is used to create output\r
++ * structured as maps (with key/value pairs), lists and primitives\r
++ * (strings, integers and booleans).\r
++ */\r
++typedef struct sprinter {\r
++    /* Start a new map/dictionary structure. This should be followed by\r
++     * a sequence of alternating calls to map_key and one of the\r
++     * value-printing functions until the map is ended by end.\r
++     */\r
++    void (*begin_map) (struct sprinter *);\r
++\r
++    /* Start a new list/array structure.\r
++     */\r
++    void (*begin_list) (struct sprinter *);\r
++\r
++    /* End the last opened list or map structure.\r
++     */\r
++    void (*end) (struct sprinter *);\r
++\r
++    /* Print one string/integer/boolean/null element (possibly inside a\r
++     * list or map, followed or preceded by separators).\r
++     * For string, the char * must be UTF-8 encoded.\r
++     */\r
++    void (*string) (struct sprinter *, const char *);\r
++    void (*integer) (struct sprinter *, int);\r
++    void (*boolean) (struct sprinter *, notmuch_bool_t);\r
++    void (*null) (struct sprinter *);\r
++\r
++    /* Print the key of a map's key/value pair. The char * must be UTF-8\r
++     * encoded.\r
++     */\r
++    void (*map_key) (struct sprinter *, const char *);\r
++\r
++    /* Insert a separator (usually extra whitespace) for improved\r
++     * readability without affecting the abstract syntax of the\r
++     * structure being printed.\r
++     * For JSON, this could simply be a line break.\r
++     */\r
++    void (*separator) (struct sprinter *);\r
++\r
++    /* Set the current string prefix. This only affects the text\r
++     * printer, which will print this string, followed by a colon,\r
++     * before any string. For other printers, this does nothing.\r
++     */\r
++    void (*set_prefix) (struct sprinter *, const char *);\r
++\r
++    /* Return TRUE if this is a text printer. Some special casing\r
++     * applies to the pure plain text printer. This should always\r
++     * return FALSE in custom structured output printers.\r
++     */ \r
++    notmuch_bool_t (*is_text_printer) (struct sprinter *);\r
++} sprinter_t;\r
++\r
++#endif // NOTMUCH_SPRINTER_H\r
+-- \r
+1.7.11.1\r
+\r