Re: [PATCH] emacs: wash: make word-wrap bound message width
[notmuch-archives.git] / 05 / ea0a953804a7e91620d0bda1e19cae8d8fadd5
1 Return-Path: <amdragon@mit.edu>\r
2 X-Original-To: notmuch@notmuchmail.org\r
3 Delivered-To: notmuch@notmuchmail.org\r
4 Received: from localhost (localhost [127.0.0.1])\r
5         by olra.theworths.org (Postfix) with ESMTP id CBB7F429E25\r
6         for <notmuch@notmuchmail.org>; Thu, 12 Jul 2012 15:07:09 -0700 (PDT)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: -0.7\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5\r
12         tests=[RCVD_IN_DNSWL_LOW=-0.7] autolearn=disabled\r
13 Received: from olra.theworths.org ([127.0.0.1])\r
14         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
15         with ESMTP id jEGa1-+WJEDK for <notmuch@notmuchmail.org>;\r
16         Thu, 12 Jul 2012 15:07:08 -0700 (PDT)\r
17 Received: from dmz-mailsec-scanner-8.mit.edu (DMZ-MAILSEC-SCANNER-8.MIT.EDU\r
18         [18.7.68.37])\r
19         by olra.theworths.org (Postfix) with ESMTP id 4F29C431FC4\r
20         for <notmuch@notmuchmail.org>; Thu, 12 Jul 2012 15:07:08 -0700 (PDT)\r
21 X-AuditID: 12074425-b7f9b6d0000008c4-2d-4fff4a8a9e35\r
22 Received: from mailhub-auth-4.mit.edu ( [18.7.62.39])\r
23         by dmz-mailsec-scanner-8.mit.edu (Symantec Messaging Gateway) with SMTP\r
24         id F6.63.02244.A8A4FFF4; Thu, 12 Jul 2012 18:07:06 -0400 (EDT)\r
25 Received: from outgoing.mit.edu (OUTGOING-AUTH.MIT.EDU [18.7.22.103])\r
26         by mailhub-auth-4.mit.edu (8.13.8/8.9.2) with ESMTP id q6CM75Jq002528; \r
27         Thu, 12 Jul 2012 18:07:05 -0400\r
28 Received: from awakening.csail.mit.edu (awakening.csail.mit.edu [18.26.4.91])\r
29         (authenticated bits=0)\r
30         (User authenticated as amdragon@ATHENA.MIT.EDU)\r
31         by outgoing.mit.edu (8.13.6/8.12.4) with ESMTP id q6CM744i028805\r
32         (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NOT);\r
33         Thu, 12 Jul 2012 18:07:05 -0400 (EDT)\r
34 Received: from amthrax by awakening.csail.mit.edu with local (Exim 4.77)\r
35         (envelope-from <amdragon@mit.edu>)\r
36         id 1SpRXM-0004sD-2W; Thu, 12 Jul 2012 18:07:04 -0400\r
37 Date: Thu, 12 Jul 2012 18:07:04 -0400\r
38 From: Austin Clements <amdragon@MIT.EDU>\r
39 To: craven@gmx.net\r
40 Subject: Re: [PATCH v4 2/3] Add structured output formatter for JSON.\r
41 Message-ID: <20120712220703.GI7332@mit.edu>\r
42 References: <87d34hsdx8.fsf@awakening.csail.mit.edu>\r
43         <1342079004-5300-1-git-send-email-craven@gmx.net>\r
44         <1342079004-5300-3-git-send-email-craven@gmx.net>\r
45 MIME-Version: 1.0\r
46 Content-Type: text/plain; charset=us-ascii\r
47 Content-Disposition: inline\r
48 In-Reply-To: <1342079004-5300-3-git-send-email-craven@gmx.net>\r
49 User-Agent: Mutt/1.5.21 (2010-09-15)\r
50 X-Brightmail-Tracker:\r
51  H4sIAAAAAAAAA+NgFmplleLIzCtJLcpLzFFi42IRYrdT1+3y+u9v8H82q8XehnZGi+s3ZzI7\r
52         MHks3rSfzePZqlvMAUxRXDYpqTmZZalF+nYJXBm7G3ewF0zTrzj09xRzA+M+5S5GTg4JAROJ\r
53         49s+sUDYYhIX7q1n62Lk4hAS2McoseX9GXYIZwOjxMtt/1ghnJNMErP+wDhLGCX+Lv0D1s8i\r
54         oCpx4c9GMJtNQENi2/7ljCC2iICQxKQvr8DizALSEt9+NzOB2MICrhKtT9+A2bwC2hKLL/yF\r
55         2j2HUaL1+RtWiISgxMmZT6CatSRu/HsJ1MABNmj5Pw6QMKeAncSdGz3sILaogIrElJPb2CYw\r
56         Cs1C0j0LSfcshO4FjMyrGGVTcqt0cxMzc4pTk3WLkxPz8lKLdC30cjNL9FJTSjcxgkPbRXUH\r
57         44RDSocYBTgYlXh4d6776y/EmlhWXJl7iFGSg0lJlNfa9b+/EF9SfkplRmJxRnxRaU5q8SFG\r
58         CQ5mJRHedfZAOd6UxMqq1KJ8mJQ0B4uSOO+NlJv+QgLpiSWp2ampBalFMFkZDg4lCd4tnkCN\r
59         gkWp6akVaZk5JQhpJg5OkOE8QMNngdTwFhck5hZnpkPkTzEqSonzzgdJCIAkMkrz4HphqecV\r
60         ozjQK8K8C0CqeIBpC677FdBgJpDBP/+BDC5JREhJNTBuWqHr58561eXNtkO/rv+vbjIIFJvN\r
61         3nm1RiDCT6dtwuNlZ9Yp3xMvjhe/9CfIO818+45t/947TI+oDfywMqJX8cakN7P3Se2ebuIz\r
62         wfrJ9V8MEqVLduX/k/auDZ/xl8/5zZq1dTVvl/qnSa0VLN6uJuDWtjY+z9lmS0LM6WexBXZS\r
63         a/4f/2ekxFKckWioxVxUnAgAfQM9CRgDAAA=\r
64 Cc: notmuch@notmuchmail.org\r
65 X-BeenThere: notmuch@notmuchmail.org\r
66 X-Mailman-Version: 2.1.13\r
67 Precedence: list\r
68 List-Id: "Use and development of the notmuch mail system."\r
69         <notmuch.notmuchmail.org>\r
70 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
71         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
72 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
73 List-Post: <mailto:notmuch@notmuchmail.org>\r
74 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
75 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
76         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
77 X-List-Received-Date: Thu, 12 Jul 2012 22:07:10 -0000\r
78 \r
79 Quoth craven@gmx.net on Jul 12 at  9:43 am:\r
80 > Using the new structured printer support in sprinter.h, implement\r
81 > sprinter_json_new, which returns a new JSON structured output\r
82 > formatter.\r
83\r
84 > The formatter prints output similar to the existing JSON, but with\r
85 > differences in whitespace (mostly newlines).\r
86 > ---\r
87 >  Makefile.local |   1 +\r
88 >  sprinter.c     | 172 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
89 >  2 files changed, 173 insertions(+)\r
90 >  create mode 100644 sprinter.c\r
91\r
92 > diff --git a/Makefile.local b/Makefile.local\r
93 > index a890df2..8baf0c2 100644\r
94 > --- a/Makefile.local\r
95 > +++ b/Makefile.local\r
96 > @@ -290,6 +290,7 @@ notmuch_client_srcs =             \\r
97 >       notmuch-show.c          \\r
98 >       notmuch-tag.c           \\r
99 >       notmuch-time.c          \\r
100 > +     sprinter.c              \\r
101 >       query-string.c          \\r
102 >       mime-node.c             \\r
103 >       crypto.c                \\r
104 > diff --git a/sprinter.c b/sprinter.c\r
105 > new file mode 100644\r
106 > index 0000000..649f79a\r
107 > --- /dev/null\r
108 > +++ b/sprinter.c\r
109 > @@ -0,0 +1,172 @@\r
110 > +#include <stdbool.h>\r
111 > +#include <stdio.h>\r
112 > +#include <talloc.h>\r
113 > +#include "sprinter.h"\r
114 > +\r
115 > +#define ARRAY_SIZE(arr) (sizeof (arr) / sizeof (arr[0]))\r
116 > +\r
117 > +struct sprinter *\r
118 > +sprinter_text = NULL;\r
119 > +\r
120 > +/*\r
121 > + * Every below here is the implementation of the JSON printer.\r
122 \r
123 s/Every/Everything/\r
124 \r
125 Or this can be shortened to just\r
126 \r
127 /*\r
128  * JSON printer\r
129  */\r
130 \r
131 If we wind up with separate files for the JSON and S-exp printers, I\r
132 don't think this comment is necessary at all.\r
133 \r
134 > + */\r
135 > +\r
136 > +struct sprinter_json\r
137 > +{\r
138 > +    struct sprinter vtable;\r
139 > +    FILE *stream;\r
140 > +    /* Top of the state stack, or NULL if the printer is not currently\r
141 > +     * inside any aggregate types. */\r
142 > +    struct json_state *state;\r
143 > +};\r
144 > +\r
145 > +struct json_state\r
146 > +{\r
147 > +    struct json_state *parent;\r
148 > +    /* True if nothing has been printed in this aggregate yet.\r
149 > +     * Suppresses the comma before a value. */\r
150 > +    notmuch_bool_t first;\r
151 > +    /* The character that closes the current aggregate. */\r
152 > +    char close;\r
153 > +};\r
154 > +\r
155 > +/* Helper function to set up the stream to print a value.  If this\r
156 > + * value follows another value, prints a comma. */\r
157 > +static struct sprinter_json *\r
158 > +json_begin_value(struct sprinter *sp)\r
159 \r
160 As Tomi pointed out, there should be spaces before the parameter\r
161 lists (sorry).\r
162 \r
163 > +{\r
164 > +    struct sprinter_json *spj = (struct sprinter_json*)sp;\r
165 > +    if (spj->state) {\r
166 > +     if (!spj->state->first)\r
167 > +         fputs (", ", spj->stream);\r
168 > +     else\r
169 > +         spj->state->first = false;\r
170 > +    }\r
171 > +    return spj;\r
172 > +}\r
173 > +\r
174 > +/* Helper function to begin an aggregate type.  Prints the open\r
175 > + * character and pushes a new state frame. */\r
176 > +static void\r
177 > +json_begin_aggregate(struct sprinter *sp, char open, char close)\r
178 > +{\r
179 > +    struct sprinter_json *spj = json_begin_value (sp);\r
180 > +    struct json_state *state = talloc (spj, struct json_state);\r
181 > +\r
182 > +    fputc (open, spj->stream);\r
183 > +    state->parent = spj->state;\r
184 > +    state->first = true;\r
185 > +    state->close = close;\r
186 > +    spj->state = state;\r
187 > +}\r
188 > +\r
189 > +static void\r
190 > +json_begin_map(struct sprinter *sp)\r
191 > +{\r
192 > +    json_begin_aggregate (sp, '{', '}');\r
193 > +}\r
194 > +\r
195 > +static void\r
196 > +json_begin_list(struct sprinter *sp)\r
197 > +{\r
198 > +    json_begin_aggregate (sp, '[', ']');\r
199 > +}\r
200 > +\r
201 > +static void\r
202 > +json_end(struct sprinter *sp)\r
203 > +{\r
204 > +    struct sprinter_json *spj = (struct sprinter_json*)sp;\r
205 > +    struct json_state *state = spj->state;\r
206 > +\r
207 > +    fputc (spj->state->close, spj->stream);\r
208 > +    spj->state = state->parent;\r
209 > +    talloc_free (state);\r
210 > +    if(spj->state == NULL)\r
211 \r
212 Ah, another missing space.\r
213 \r
214 > +     fputc ('\n', spj->stream);\r
215 > +}\r
216 > +\r
217 > +static void\r
218 > +json_string(struct sprinter *sp, const char *val)\r
219 > +{\r
220 > +    static const char * const escapes[] = {\r
221 > +     ['\"'] = "\\\"", ['\\'] = "\\\\", ['\b'] = "\\b",\r
222 > +     ['\f'] = "\\f",  ['\n'] = "\\n",  ['\t'] = "\\t"\r
223 > +    };\r
224 > +    struct sprinter_json *spj = json_begin_value (sp);\r
225 > +    fputc ('"', spj->stream);\r
226 > +    for (; *val; ++val) {\r
227 > +     unsigned char ch = *val;\r
228 > +     if (ch < ARRAY_SIZE(escapes) && escapes[ch])\r
229 > +         fputs (escapes[ch], spj->stream);\r
230 > +     else if (ch >= 32)\r
231 > +         fputc (ch, spj->stream);\r
232 > +     else\r
233 > +         fprintf (spj->stream, "\\u%04x", ch);\r
234 > +    }\r
235 > +    fputc ('"', spj->stream);\r
236 > +}\r
237 > +\r
238 > +static void\r
239 > +json_integer(struct sprinter *sp, int val)\r
240 > +{\r
241 > +    struct sprinter_json *spj = json_begin_value (sp);\r
242 > +    fprintf (spj->stream, "%d", val);\r
243 > +}\r
244 > +\r
245 > +static void\r
246 > +json_boolean(struct sprinter *sp, notmuch_bool_t val)\r
247 > +{\r
248 > +    struct sprinter_json *spj = json_begin_value (sp);\r
249 > +    fputs (val ? "true" : "false", spj->stream);\r
250 > +}\r
251 > +\r
252 > +static void\r
253 > +json_null(struct sprinter *sp)\r
254 > +{\r
255 > +    struct sprinter_json *spj = json_begin_value (sp);\r
256 > +    fputs ("null", spj->stream);\r
257 > +}\r
258 > +\r
259 > +static void\r
260 > +json_map_key(struct sprinter *sp, const char *key)\r
261 > +{\r
262 > +    struct sprinter_json *spj = (struct sprinter_json*)sp;\r
263 > +    json_string (sp, key);\r
264 > +    fputs (": ", spj->stream);\r
265 > +    spj->state->first = true;\r
266 > +}\r
267 > +\r
268 > +static void\r
269 > +json_frame(struct sprinter *sp)\r
270 > +{\r
271 > +    struct sprinter_json *spj = (struct sprinter_json*)sp;\r
272 > +    fputc ('\n', spj->stream);\r
273 > +}\r
274 > +\r
275 > +struct sprinter *\r
276 > +sprinter_json_new(const void *ctx, FILE *stream)\r
277 > +{\r
278 > +    static const struct sprinter_json template = {\r
279 > +     .vtable = {\r
280 > +         .begin_map = json_begin_map,\r
281 > +         .begin_list = json_begin_list,\r
282 > +         .end = json_end,\r
283 > +         .string = json_string,\r
284 > +         .integer = json_integer,\r
285 > +         .boolean = json_boolean,\r
286 > +         .null = json_null,\r
287 > +         .map_key = json_map_key,\r
288 > +         .frame = json_frame,\r
289 > +     }\r
290 > +    };\r
291 > +    struct sprinter_json *res;\r
292 > +\r
293 > +    res = talloc (ctx, struct sprinter_json);\r
294 > +    if (!res)\r
295 > +     return NULL;\r
296 > +\r
297 > +    *res = template;\r
298 > +    res->stream = stream;\r
299 > +    return &res->vtable;\r
300 > +}\r