CLI: stash pointer to database in sprinter structs We already use an allocated (and presumably open) database as a talloc context. Keeping the pointer in the allocated struct will allow us to e.g. interrogate the configuration in a sprinter function without threading the database all the way through the various levels of function.
sprinter: change integer method to use int64_t In particular, timestamps beyond 2038 could overflow the sprinter interface on systems where time_t is 64-bit but 'int' is a signed 32-bit integer type.
cli: run uncrustify This is the result of running $ uncrustify --replace --config devel/uncrustify.cfg *.c *.h in the top level source directory
cli: convert notmuch_bool_t to stdbool C99 stdbool turned 18 this year. There really is no reason to use our own, except in the library interface for backward compatibility. Convert the cli and test binaries to stdbool.
sprinter: add text0 formatter for null character separated text Same as the text formatter, but with each field separated by a null character rather than a newline character.
sprinter: clarify separator documentation For text printers, the separator is a syntactic element.
Adding an S-expression structured output printer. This commit adds a structured output printer for Lisp S-Expressions. Later commits will use this printer in notmuch search, show and reply. The structure is the same as json, but: - arrays are written as lists: ("foo" "bar" "baaz" 1 2 3) - maps are written as p-lists: (:key "value" :other-key "other-value") - true is written as t - false is written as nil - null is written as nil [ whitespace changes by db ]
sprinters: bugfix when NULL passed for a string. The string function in a sprinter may be called with a NULL string pointer (eg if a header is absent). This causes a segfault. We fix this by checking for a null pointer in the string functions and update the sprinter documentation. At the moment some output when format=text is done directly rather than via an sprinter: in that case a null pointer is passed to printf or similar and a "(null)" appears in the output. That behaviour is not changed in this patch.
sprinter: Add a string_len method This method allows callers to output strings with specific lengths. It's useful both for strings with embedded NULs (which JSON can represent, though parser support is apparently spotty), and non-terminated strings.
Add structured output formatter for JSON and plain text (but don't use them yet). Using the new structured printer support in sprinter.h, implement sprinter_json_create, which returns a new JSON structured output formatter. The formatter prints output similar to the existing JSON, but with differences in whitespace (mostly newlines, --output=summary prints the entire message summary on one line, not split across multiple lines). Also implement a "structured" formatter for plain text that prints prefixed strings, to be used with notmuch-search.c plain text output.
Add support for structured output formatters. 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 *); /* 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 *); To support the plain text format properly, the following additional function 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 *); The structure also contains a flag that should be set to FALSE in all custom printers and to TRUE in the plain text formatter. /* True if this is the special-cased plain text printer. */ notmuch_bool_t is_text_printer; 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"}}