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