On IRC today, Peter renewed discussions of supporting an S-expression format, which I think would be a fantastic thing to have. A while back [1] I tried to explain an API I thought would form a good foundation for this by abstracting away the differences between JSON and S-expression output so both structured formats can use the same code, but I didn't express the idea very clearly. I built essentially this API for another project recently and it worked well (and I learned a few things), so I figured I would give it another shot. It's simple enough that I tossed together an example implementation, which is attached. The idea is similar to the existing format structures, but instead of dealing with complex, high-level concepts like threads or messages, this API deals with syntax-level concepts like lists and strings. All of the structured output formats can then be supported by a single high-level formatter backed by different syntax formatters. There are a few ways something like this could be integrated with the high-level formatters. For show, the least invasive thing would be to have two notmuch_show_format structures with different part functions. These part functions would be thin wrappers that simply create the right structure printer and then pass it to a common part function. It would be even nicer if we could get rid of the message_set_{start,sep,end} fields, since those duplicate functionality from the structure printer and their use is haphazard and overly complicated. We could do this by changing notmuch_show_format to something like typedef struct notmuch_show_format { struct sprinter *(*new_sprinter) (const void *ctx); notmuch_status_t (*part) (const void *ctx, struct sprinter *sp, struct mime_node *node, const struct notmuch_show_params *params); } notmuch_show_format_t; For the JSON and S-expression show formats, new_sprinter would be sprinter_json_new and sprinter_sexp_new, respectively, and they could share a part function. For the text, mbox, and raw formatters, new_sprinter could simply be NULL, or we could provide a "NULL structure printer" implementation that does nothing. We could do something similar for reply. search_format is more complicated, but might also benefit more. Most of those fields have to do with how to print lists and objects and could be removed if the format simply provided a new_sprinter method like the notmuch_show_format I suggested above. [1] id:"20120121220407.GK16740@mit.edu"