Re: [PATCH] emacs: wash: make word-wrap bound message width
[notmuch-archives.git] / d9 / 0e84e3bafb016cef463ad1ecc74beaf9e37a0b
1 Return-Path: <amthrax@drake.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 A2194431FC0\r
6         for <notmuch@notmuchmail.org>; Sun, 19 Feb 2012 16:26:42 -0800 (PST)\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 PSUr2-gbISBf for <notmuch@notmuchmail.org>;\r
16         Sun, 19 Feb 2012 16:26:39 -0800 (PST)\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 67E43431FC3\r
20         for <notmuch@notmuchmail.org>; Sun, 19 Feb 2012 16:26:36 -0800 (PST)\r
21 X-AuditID: 12074425-b7f4a6d0000008e0-bf-4f41933b105c\r
22 Received: from mailhub-auth-3.mit.edu ( [18.9.21.43])\r
23         by dmz-mailsec-scanner-8.mit.edu (Symantec Messaging Gateway) with SMTP\r
24         id 62.74.02272.B33914F4; Sun, 19 Feb 2012 19:26:35 -0500 (EST)\r
25 Received: from outgoing.mit.edu (OUTGOING-AUTH.MIT.EDU [18.7.22.103])\r
26         by mailhub-auth-3.mit.edu (8.13.8/8.9.2) with ESMTP id q1K0QZms024836; \r
27         Sun, 19 Feb 2012 19:26:35 -0500\r
28 Received: from drake.mit.edu\r
29         (209-6-116-242.c3-0.arl-ubr1.sbo-arl.ma.cable.rcn.com\r
30         [209.6.116.242]) (authenticated bits=0)\r
31         (User authenticated as amdragon@ATHENA.MIT.EDU)\r
32         by outgoing.mit.edu (8.13.6/8.12.4) with ESMTP id q1K0QXr6000300\r
33         (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NOT);\r
34         Sun, 19 Feb 2012 19:26:34 -0500 (EST)\r
35 Received: from amthrax by drake.mit.edu with local (Exim 4.77)\r
36         (envelope-from <amthrax@drake.mit.edu>)\r
37         id 1RzH5N-0001yF-Cc; Sun, 19 Feb 2012 19:26:33 -0500\r
38 From: Austin Clements <amdragon@MIT.EDU>\r
39 To: notmuch@notmuchmail.org\r
40 Subject: [PATCH v2 2/8] show: Convert JSON format to the new self-recursive\r
41         style\r
42 Date: Sun, 19 Feb 2012 19:26:24 -0500\r
43 Message-Id: <1329697590-7404-3-git-send-email-amdragon@mit.edu>\r
44 X-Mailer: git-send-email 1.7.7.3\r
45 In-Reply-To: <1329697590-7404-1-git-send-email-amdragon@mit.edu>\r
46 References: <1329240823-7856-1-git-send-email-amdragon@mit.edu>\r
47         <1329697590-7404-1-git-send-email-amdragon@mit.edu>\r
48 X-Brightmail-Tracker:\r
49  H4sIAAAAAAAAA+NgFtrNIsWRmVeSWpSXmKPExsUixCmqrWs92dHfoP+RscX1mzOZLd6snMfq\r
50         wORx+OtCFo9nq24xBzBFcdmkpOZklqUW6dslcGV8PPmYsaAjqOLkrLIGxtuOXYycHBICJhIv\r
51         9vWzQdhiEhfurQeyuTiEBPYxSjSeesoE4WxglFg3tZcVwrnPJHHk1U+osvmMErN657KC9LMJ\r
52         aEhs27+cEcQWEZCW2Hl3NlicWcBK4vDVTUA2B4ewQKDEvR59kDCLgKrEv5lLWEBsXgF7iQmv\r
53         rjBBnKEgcW71OXaQck4BB4nVO1xBwkICpRJHnmxhmsDIv4CRYRWjbEpulW5uYmZOcWqybnFy\r
54         Yl5eapGuhV5uZoleakrpJkZQGLG7qO5gnHBI6RCjAAejEg+vZJmDvxBrYllxZe4hRkkOJiVR\r
55         3nWTHP2F+JLyUyozEosz4otKc1KLDzFKcDArifAusAfK8aYkVlalFuXDpKQ5WJTEeTW13vkJ\r
56         CaQnlqRmp6YWpBbBZGU4OJQkeHeBDBUsSk1PrUjLzClBSDNxcIIM5wEaPhukhre4IDG3ODMd\r
57         In+KUVFKnLceJCEAksgozYPrhcX5K0ZxoFeEeVeAVPEAUwRc9yugwUxAg3mF7EAGlyQipKQa\r
58         GGt/breTWuST2v7i2QTpm+nvlLaIn1PNtlP7zpI8b0N7parfZWMtR7UY5SfHFFWnbHywzdZb\r
59         ct7E1Z/8Chz4b3842xPDfOjerNCHFixMJ5x+VHn/Zg2a52qcdvBD3pP1wZf/2ATyzGc/9GPW\r
60         BJ/sHIs5crM80nQ3d+rtPLc7psulkuf0kwdbtJRYijMSDbWYi4oTAfWiKVDOAgAA\r
61 Cc: tomi.ollila@iki.fi\r
62 X-BeenThere: notmuch@notmuchmail.org\r
63 X-Mailman-Version: 2.1.13\r
64 Precedence: list\r
65 List-Id: "Use and development of the notmuch mail system."\r
66         <notmuch.notmuchmail.org>\r
67 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
68         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
69 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
70 List-Post: <mailto:notmuch@notmuchmail.org>\r
71 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
72 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
73         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
74 X-List-Received-Date: Mon, 20 Feb 2012 00:26:43 -0000\r
75 \r
76 As before, this is all code movement and a smidgen of glue.  This\r
77 moves the existing JSON formatter code into one self-recursive\r
78 function, but doesn't change any of the logic to take advantage of the\r
79 new structure.\r
80 \r
81 In general, "leafs" of the JSON structure are left in helper functions\r
82 (most of them untouched), so that it's easy to see the overall\r
83 structure of the format from the main recursive function.\r
84 ---\r
85  notmuch-show.c |  273 ++++++++++++++++++++++++++++----------------------------\r
86  1 files changed, 135 insertions(+), 138 deletions(-)\r
87 \r
88 diff --git a/notmuch-show.c b/notmuch-show.c\r
89 index 93fb16f..868b2cd 100644\r
90 --- a/notmuch-show.c\r
91 +++ b/notmuch-show.c\r
92 @@ -35,52 +35,14 @@ static const notmuch_show_format_t format_text = {\r
93  };\r
94  \r
95  static void\r
96 -format_message_json (const void *ctx,\r
97 -                    notmuch_message_t *message,\r
98 -                    unused (int indent));\r
99 -static void\r
100 -format_headers_json (const void *ctx,\r
101 -                    notmuch_message_t *message);\r
102 +format_part_json_entry (const void *ctx, mime_node_t *node,\r
103 +                       int indent, const notmuch_show_params_t *params);\r
104  \r
105 -static void\r
106 -format_headers_message_part_json (GMimeMessage *message);\r
107 -\r
108 -static void\r
109 -format_part_start_json (unused (GMimeObject *part),\r
110 -                       int *part_count);\r
111 -\r
112 -static void\r
113 -format_part_encstatus_json (int status);\r
114 -\r
115 -static void\r
116 -#ifdef GMIME_ATLEAST_26\r
117 -format_part_sigstatus_json (GMimeSignatureList* siglist);\r
118 -#else\r
119 -format_part_sigstatus_json (const GMimeSignatureValidity* validity);\r
120 -#endif\r
121 -\r
122 -static void\r
123 -format_part_content_json (GMimeObject *part);\r
124 -\r
125 -static void\r
126 -format_part_end_json (GMimeObject *part);\r
127 -\r
128 -/* Any changes to the JSON format should be reflected in the file\r
129 - * devel/schemata. */\r
130  static const notmuch_show_format_t format_json = {\r
131 -    "[", NULL,\r
132 -       "{", format_message_json,\r
133 -           "\"headers\": {", format_headers_json, format_headers_message_part_json, "}",\r
134 -           ", \"body\": [",\r
135 -               format_part_start_json,\r
136 -               format_part_encstatus_json,\r
137 -               format_part_sigstatus_json,\r
138 -               format_part_content_json,\r
139 -               format_part_end_json,\r
140 -               ", ",\r
141 -           "]",\r
142 -       "}", ", ",\r
143 -    "]"\r
144 +    .message_set_start = "[",\r
145 +    .part = format_part_json_entry,\r
146 +    .message_set_sep = ", ",\r
147 +    .message_set_end = "]"\r
148  };\r
149  \r
150  static void\r
151 @@ -170,7 +132,7 @@ _get_one_line_summary (const void *ctx, notmuch_message_t *message)\r
152  }\r
153  \r
154  static void\r
155 -format_message_json (const void *ctx, notmuch_message_t *message, unused (int indent))\r
156 +format_message_json (const void *ctx, notmuch_message_t *message)\r
157  {\r
158      notmuch_tags_t *tags;\r
159      int first = 1;\r
160 @@ -471,24 +433,6 @@ signer_status_to_string (GMimeSignerStatus x)\r
161  }\r
162  #endif\r
163  \r
164 -static void\r
165 -format_part_start_json (unused (GMimeObject *part), int *part_count)\r
166 -{\r
167 -    printf ("{\"id\": %d", *part_count);\r
168 -}\r
169 -\r
170 -static void\r
171 -format_part_encstatus_json (int status)\r
172 -{\r
173 -    printf (", \"encstatus\": [{\"status\": ");\r
174 -    if (status) {\r
175 -       printf ("\"good\"");\r
176 -    } else {\r
177 -       printf ("\"bad\"");\r
178 -    }\r
179 -    printf ("}]");\r
180 -}\r
181 -\r
182  #ifdef GMIME_ATLEAST_26\r
183  static void\r
184  format_part_sigstatus_json (GMimeSignatureList *siglist)\r
185 @@ -619,81 +563,6 @@ format_part_sigstatus_json (const GMimeSignatureValidity* validity)\r
186  #endif\r
187  \r
188  static void\r
189 -format_part_content_json (GMimeObject *part)\r
190 -{\r
191 -    GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));\r
192 -    GMimeStream *stream_memory = g_mime_stream_mem_new ();\r
193 -    const char *cid = g_mime_object_get_content_id (part);\r
194 -    void *ctx = talloc_new (NULL);\r
195 -    GByteArray *part_content;\r
196 -\r
197 -    printf (", \"content-type\": %s",\r
198 -           json_quote_str (ctx, g_mime_content_type_to_string (content_type)));\r
199 -\r
200 -    if (cid != NULL)\r
201 -           printf(", \"content-id\": %s", json_quote_str (ctx, cid));\r
202 -\r
203 -    if (GMIME_IS_PART (part))\r
204 -    {\r
205 -       const char *filename = g_mime_part_get_filename (GMIME_PART (part));\r
206 -       if (filename)\r
207 -           printf (", \"filename\": %s", json_quote_str (ctx, filename));\r
208 -    }\r
209 -\r
210 -    if (g_mime_content_type_is_type (content_type, "text", "*"))\r
211 -    {\r
212 -       /* For non-HTML text parts, we include the content in the\r
213 -        * JSON. Since JSON must be Unicode, we handle charset\r
214 -        * decoding here and do not report a charset to the caller.\r
215 -        * For text/html parts, we do not include the content. If a\r
216 -        * caller is interested in text/html parts, it should retrieve\r
217 -        * them separately and they will not be decoded. Since this\r
218 -        * makes charset decoding the responsibility on the caller, we\r
219 -        * report the charset for text/html parts.\r
220 -        */\r
221 -       if (g_mime_content_type_is_type (content_type, "text", "html"))\r
222 -       {\r
223 -           const char *content_charset = g_mime_object_get_content_type_parameter (GMIME_OBJECT (part), "charset");\r
224 -\r
225 -           if (content_charset != NULL)\r
226 -               printf (", \"content-charset\": %s", json_quote_str (ctx, content_charset));\r
227 -       }\r
228 -       else\r
229 -       {\r
230 -           show_text_part_content (part, stream_memory);\r
231 -           part_content = g_mime_stream_mem_get_byte_array (GMIME_STREAM_MEM (stream_memory));\r
232 -\r
233 -           printf (", \"content\": %s", json_quote_chararray (ctx, (char *) part_content->data, part_content->len));\r
234 -       }\r
235 -    }\r
236 -    else if (g_mime_content_type_is_type (content_type, "multipart", "*"))\r
237 -    {\r
238 -       printf (", \"content\": [");\r
239 -    }\r
240 -    else if (g_mime_content_type_is_type (content_type, "message", "rfc822"))\r
241 -    {\r
242 -       printf (", \"content\": [{");\r
243 -    }\r
244 -\r
245 -    talloc_free (ctx);\r
246 -    if (stream_memory)\r
247 -       g_object_unref (stream_memory);\r
248 -}\r
249 -\r
250 -static void\r
251 -format_part_end_json (GMimeObject *part)\r
252 -{\r
253 -    GMimeContentType *content_type = g_mime_object_get_content_type (GMIME_OBJECT (part));\r
254 -\r
255 -    if (g_mime_content_type_is_type (content_type, "multipart", "*"))\r
256 -       printf ("]");\r
257 -    else if (g_mime_content_type_is_type (content_type, "message", "rfc822"))\r
258 -       printf ("}]");\r
259 -\r
260 -    printf ("}");\r
261 -}\r
262 -\r
263 -static void\r
264  format_part_content_raw (GMimeObject *part)\r
265  {\r
266      if (! GMIME_IS_PART (part))\r
267 @@ -811,6 +680,134 @@ format_part_text (const void *ctx, mime_node_t *node,\r
268  }\r
269  \r
270  static void\r
271 +format_part_json (const void *ctx, mime_node_t *node, notmuch_bool_t first)\r
272 +{\r
273 +    /* Any changes to the JSON format should be reflected in the file\r
274 +     * devel/schemata. */\r
275 +\r
276 +    if (node->envelope_file) {\r
277 +       printf ("{");\r
278 +       format_message_json (ctx, node->envelope_file);\r
279 +\r
280 +       printf ("\"headers\": {");\r
281 +       format_headers_json (ctx, node->envelope_file);\r
282 +       printf ("}");\r
283 +\r
284 +       printf (", \"body\": [");\r
285 +       format_part_json (ctx, mime_node_child (node, 0), first);\r
286 +\r
287 +       printf ("]}");\r
288 +       return;\r
289 +    }\r
290 +\r
291 +    void *local = talloc_new (ctx);\r
292 +    /* The disposition and content-type metadata are associated with\r
293 +     * the envelope for message parts */\r
294 +    GMimeObject *meta = node->envelope_part ?\r
295 +       GMIME_OBJECT (node->envelope_part) : node->part;\r
296 +    GMimeContentType *content_type = g_mime_object_get_content_type (meta);\r
297 +    GMimeStream *stream_memory = g_mime_stream_mem_new ();\r
298 +    const char *cid = g_mime_object_get_content_id (meta);\r
299 +    GByteArray *part_content;\r
300 +    int i;\r
301 +\r
302 +    if (!first)\r
303 +       printf (", ");\r
304 +\r
305 +    printf ("{\"id\": %d", node->part_num);\r
306 +\r
307 +    if (node->decrypt_attempted) {\r
308 +       printf (", \"encstatus\": [{\"status\": ");\r
309 +       if (node->decrypt_success) {\r
310 +           printf ("\"good\"");\r
311 +       } else {\r
312 +           printf ("\"bad\"");\r
313 +       }\r
314 +       printf ("}]");\r
315 +    }\r
316 +\r
317 +    if (node->verify_attempted) {\r
318 +#ifdef GMIME_ATLEAST_26\r
319 +       format_part_sigstatus_json (node->sig_list);\r
320 +#else\r
321 +       format_part_sigstatus_json (node->sig_validity);\r
322 +#endif\r
323 +    }\r
324 +\r
325 +    printf (", \"content-type\": %s",\r
326 +           json_quote_str (local, g_mime_content_type_to_string (content_type)));\r
327 +\r
328 +    if (cid != NULL)\r
329 +           printf(", \"content-id\": %s", json_quote_str (local, cid));\r
330 +\r
331 +    if (GMIME_IS_PART (node->part)) {\r
332 +       const char *filename = g_mime_part_get_filename (GMIME_PART (node->part));\r
333 +       if (filename)\r
334 +           printf (", \"filename\": %s", json_quote_str (local, filename));\r
335 +    }\r
336 +\r
337 +    if (g_mime_content_type_is_type (content_type, "text", "*")) {\r
338 +       /* For non-HTML text parts, we include the content in the\r
339 +        * JSON. Since JSON must be Unicode, we handle charset\r
340 +        * decoding here and do not report a charset to the caller.\r
341 +        * For text/html parts, we do not include the content. If a\r
342 +        * caller is interested in text/html parts, it should retrieve\r
343 +        * them separately and they will not be decoded. Since this\r
344 +        * makes charset decoding the responsibility on the caller, we\r
345 +        * report the charset for text/html parts.\r
346 +        */\r
347 +       if (g_mime_content_type_is_type (content_type, "text", "html")) {\r
348 +           const char *content_charset = g_mime_object_get_content_type_parameter (meta, "charset");\r
349 +\r
350 +           if (content_charset != NULL)\r
351 +               printf (", \"content-charset\": %s", json_quote_str (local, content_charset));\r
352 +       } else {\r
353 +           show_text_part_content (node->part, stream_memory);\r
354 +           part_content = g_mime_stream_mem_get_byte_array (GMIME_STREAM_MEM (stream_memory));\r
355 +\r
356 +           printf (", \"content\": %s", json_quote_chararray (local, (char *) part_content->data, part_content->len));\r
357 +       }\r
358 +    } else if (g_mime_content_type_is_type (content_type, "multipart", "*")) {\r
359 +       printf (", \"content\": [");\r
360 +    } else if (g_mime_content_type_is_type (content_type, "message", "rfc822")) {\r
361 +       printf (", \"content\": [{");\r
362 +    }\r
363 +\r
364 +    if (stream_memory)\r
365 +       g_object_unref (stream_memory);\r
366 +\r
367 +    if (GMIME_IS_MESSAGE (node->part)) {\r
368 +       printf ("\"headers\": {");\r
369 +       format_headers_message_part_json (GMIME_MESSAGE (node->part));\r
370 +       printf ("}");\r
371 +\r
372 +       printf (", \"body\": [");\r
373 +    }\r
374 +\r
375 +    for (i = 0; i < node->nchildren; i++)\r
376 +       format_part_json (ctx, mime_node_child (node, i), i == 0);\r
377 +\r
378 +    if (GMIME_IS_MESSAGE (node->part))\r
379 +       printf ("]");\r
380 +\r
381 +    if (g_mime_content_type_is_type (content_type, "multipart", "*"))\r
382 +       printf ("]");\r
383 +    else if (g_mime_content_type_is_type (content_type, "message", "rfc822"))\r
384 +       printf ("}]");\r
385 +\r
386 +    printf ("}");\r
387 +\r
388 +    talloc_free (local);\r
389 +}\r
390 +\r
391 +static void\r
392 +format_part_json_entry (const void *ctx, mime_node_t *node, unused (int indent),\r
393 +                       unused (const notmuch_show_params_t *params))\r
394 +{\r
395 +    format_part_json (ctx, node, TRUE);\r
396 +}\r
397 +\r
398 +static void\r
399  show_message (void *ctx,\r
400               const notmuch_show_format_t *format,\r
401               notmuch_message_t *message,\r
402 -- \r
403 1.7.7.3\r
404 \r