--- /dev/null
+Return-Path: <peter.feigl@gmx.at>\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 8EC86431FC0\r
+ for <notmuch@notmuchmail.org>; Tue, 10 Jul 2012 11:56:14 -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 Rdh+vVmivbtq for <notmuch@notmuchmail.org>;\r
+ Tue, 10 Jul 2012 11:56:13 -0700 (PDT)\r
+Received: from mailout-de.gmx.net (mailout-de.gmx.net [213.165.64.23])\r
+ by olra.theworths.org (Postfix) with SMTP id 4C6AA431FBF\r
+ for <notmuch@notmuchmail.org>; Tue, 10 Jul 2012 11:56:13 -0700 (PDT)\r
+Received: (qmail invoked by alias); 10 Jul 2012 18:56:10 -0000\r
+Received: from www.nexoid.at (EHLO mail.nexoid.at) [178.79.130.240]\r
+ by mail.gmx.net (mp031) with SMTP; 10 Jul 2012 20:56:10 +0200\r
+X-Authenticated: #4563876\r
+X-Provags-ID: V01U2FsdGVkX19Vb2BisVBVkwwxE2kmexZLYEysiJVDAUaGlOF67S\r
+ B+XR9dIoYuJIEG\r
+Received: from nexoid (localhost [127.0.0.1])\r
+ by mail.nexoid.at (Postfix) with ESMTP id 4C6AAE00C\r
+ for <notmuch@notmuchmail.org>; Tue, 10 Jul 2012 20:56:09 +0200 (CEST)\r
+From: <craven@gmx.net>\r
+To: notmuch@notmuchmail.org\r
+Subject: [PATCH v3 1/3] Add support for structured output formatters.\r
+User-Agent: Notmuch/0.11+77~gad6d0d5 (http://notmuchmail.org) Emacs/24.1.50.2\r
+ (i686-pc-linux-gnu)\r
+Date: Tue, 10 Jul 2012 20:56:09 +0200\r
+Message-ID: <87394zv41i.fsf@nexoid.at>\r
+MIME-Version: 1.0\r
+Content-Type: text/plain; charset=utf-8\r
+Content-Transfer-Encoding: quoted-printable\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, 10 Jul 2012 18:56:14 -0000\r
+\r
+This patch adds a new type structure_printer, which is used for structured =\r
+formatting, e.g. JSON or S-Expressions.\r
+\r
+The structure contains the following function pointers:\r
+\r
+- initial_state: is called to create a state object, that is passed to all =\r
+invocations. This should be used to keep track of the output file and every=\r
+thing else necessary to correctly format output.\r
+- map: is called when a new map (associative array, dictionary) is started.=\r
+ map_key and the primitives (string, number, bool) are used alternatingly t=\r
+o add key/value pairs. pop is used to close the map (see there). This funct=\r
+ion must return a nesting level identifier that can be used to close all ne=\r
+sted structures (maps and lists), backing out to the returned nesting level.\r
+- list: is called when a new list (array, vector) is started. the primitive=\r
+s (string, number, bool) are used consecutively to add values to the list. =\r
+pop is used to close the list. This function must return a nesting level id=\r
+entifier that can be used to close all nested structures (maps and lists), =\r
+backing out to the returned nesting level.\r
+- pop: is called to return to a given nesting level. All lists and maps wit=\r
+h a deeper nesting level must be closed.\r
+- number, string, bool: output one element of the specific type.\r
+\r
+All functions should use state to insert delimiters etc. automatically when=\r
+ appropriate.\r
+\r
+Example:\r
+int top, one;\r
+top =3D map(state);\r
+map_key(state, "foo");\r
+one =3D list(state);\r
+number(state, 1);\r
+number(state, 2);\r
+number(state, 3);\r
+pop(state, one);\r
+map_key(state, "bar");\r
+map(state);\r
+map_key(state, "baaz");\r
+string(state, "hello world");\r
+pop(state, top);\r
+\r
+would output JSON as follows:\r
+\r
+{"foo": [1, 2, 3], "bar": { "baaz": "hello world"}}\r
+---\r
+ Makefile.local | 1 +\r
+ structured-output.h | 64 +++++++++++++++++++++++++++++++++++++++++++++++=\r
+++++\r
+ 2 files changed, 65 insertions(+)\r
+ create mode 100644 structured-output.h\r
+\r
+diff --git a/Makefile.local b/Makefile.local\r
+index a890df2..9b3db5e 100644\r
+--- a/Makefile.local\r
++++ b/Makefile.local\r
+@@ -286,6 +286,7 @@ notmuch_client_srcs =3D \\r
+ notmuch-reply.c \\r
+ notmuch-restore.c \\r
+ notmuch-search.c \\r
++ structured-output.c \\r
+ notmuch-setup.c \\r
+ notmuch-show.c \\r
+ notmuch-tag.c \\r
+diff --git a/structured-output.h b/structured-output.h\r
+new file mode 100644\r
+index 0000000..b43afe0\r
+--- /dev/null\r
++++ b/structured-output.h\r
+@@ -0,0 +1,64 @@\r
++/* notmuch - Not much of an email program, (just index and search)\r
++ *\r
++ * Copyright =C2=A9 2009 Carl Worth\r
++ *\r
++ * This program is free software: you can redistribute it and/or modify\r
++ * it under the terms of the GNU General Public License as published by\r
++ * the Free Software Foundation, either version 3 of the License, or\r
++ * (at your option) any later version.\r
++ *\r
++ * This program is distributed in the hope that it will be useful,\r
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
++ * GNU General Public License for more details.\r
++ *\r
++ * You should have received a copy of the GNU General Public License\r
++ * along with this program. If not, see http://www.gnu.org/licenses/ .\r
++ *\r
++ * Author: Carl Worth <cworth@cworth.org>\r
++ */\r
++\r
++#include "notmuch-client.h"\r
++\r
++/* structured formatting, useful for JSON, S-Expressions, ...\r
++\r
++- initial_state: is called to create a state object, that is passed to all=\r
+ invocations. This should be used to keep track of the output file and ever=\r
+ything else necessary to correctly format output.\r
++- map: is called when a new map (associative array, dictionary) is started=\r
+. map_key and the primitives (string, number, bool) are used alternatingly =\r
+to add key/value pairs. pop is used to close the map (see there). This func=\r
+tion must return a nesting level identifier that can be used to close all n=\r
+ested structures (maps and lists), backing out to the returned nesting leve=\r
+l.\r
++- list: is called when a new list (array, vector) is started. the primitiv=\r
+es (string, number, bool) are used consecutively to add values to the list.=\r
+ pop is used to close the list. This function must return a nesting level i=\r
+dentifier that can be used to close all nested structures (maps and lists),=\r
+ backing out to the returned nesting level.\r
++- pop: is called to return to a given nesting level. All lists and maps wi=\r
+th a deeper nesting level must be closed.\r
++- number, string, bool: output one element of the specific type.\r
++\r
++All functions should use state to insert delimiters etc. automatically whe=\r
+n appropriate.\r
++\r
++Example:\r
++int top, one;\r
++top =3D map(state);\r
++map_key(state, "foo");\r
++one =3D list(state);\r
++number(state, 1);\r
++number(state, 2);\r
++number(state, 3);\r
++pop(state, one);\r
++map_key(state, "bar");\r
++map(state);\r
++map_key(state, "baaz");\r
++string(state, "hello world");\r
++pop(state, top);\r
++\r
++would output JSON as follows:\r
++\r
++{"foo": [1, 2, 3], "bar": { "baaz": "hello world"}}\r
++\r
++ */\r
++typedef struct structure_printer {\r
++ int (*map)(void *state);\r
++ int (*list)(void *state);\r
++ void (*pop)(void *state, int level);\r
++ void (*map_key)(void *state, const char *key);\r
++ void (*number)(void *state, int val);\r
++ void (*string)(void *state, const char *val);\r
++ void (*bool)(void *state, notmuch_bool_t val);\r
++ void *(*initial_state)(const struct structure_printer *sp, FILE *outpu=\r
+t);\r
++} structure_printer_t;\r
++\r
++\r
+--=20\r
+1.7.10.4\r