Re: [PATCH] emacs: wash: make word-wrap bound message width
[notmuch-archives.git] / b3 / 26fa09f7e9f9363054f865587d51652a5dea00
1 Return-Path: <peter.feigl@gmx.at>\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 99E7C431FC0\r
6         for <notmuch@notmuchmail.org>; Tue, 10 Jul 2012 11:57:27 -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.001\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=0.001 tagged_above=-999 required=5\r
12         tests=[FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001]\r
13         autolearn=disabled\r
14 Received: from olra.theworths.org ([127.0.0.1])\r
15         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
16         with ESMTP id QbrhGCsT4rqN for <notmuch@notmuchmail.org>;\r
17         Tue, 10 Jul 2012 11:57:26 -0700 (PDT)\r
18 Received: from mailout-de.gmx.net (mailout-de.gmx.net [213.165.64.22])\r
19         by olra.theworths.org (Postfix) with SMTP id 00DBF431FBF\r
20         for <notmuch@notmuchmail.org>; Tue, 10 Jul 2012 11:57:25 -0700 (PDT)\r
21 Received: (qmail invoked by alias); 10 Jul 2012 18:57:25 -0000\r
22 Received: from www.nexoid.at (EHLO mail.nexoid.at) [178.79.130.240]\r
23         by mail.gmx.net (mp030) with SMTP; 10 Jul 2012 20:57:25 +0200\r
24 X-Authenticated: #4563876\r
25 X-Provags-ID: V01U2FsdGVkX18r/OYzuJkrOPycV8a9O0gymwbiBVpqBvOxVYLqH8\r
26         iHMe+M4veqPGGg\r
27 Received: from nexoid (localhost [127.0.0.1])\r
28         by mail.nexoid.at (Postfix) with ESMTP id 12792E00C\r
29         for <notmuch@notmuchmail.org>; Tue, 10 Jul 2012 20:57:23 +0200 (CEST)\r
30 From: <craven@gmx.net>\r
31 To: notmuch@notmuchmail.org\r
32 Subject: [PATCH v3 3/3] Use the structured format printer in notmuch search.\r
33 User-Agent: Notmuch/0.11+77~gad6d0d5 (http://notmuchmail.org) Emacs/24.1.50.2\r
34         (i686-pc-linux-gnu)\r
35 Date: Tue, 10 Jul 2012 20:57:23 +0200\r
36 Message-ID: <87wr2btpf0.fsf@nexoid.at>\r
37 MIME-Version: 1.0\r
38 Content-Type: text/plain\r
39 X-Y-GMX-Trusted: 0\r
40 X-BeenThere: notmuch@notmuchmail.org\r
41 X-Mailman-Version: 2.1.13\r
42 Precedence: list\r
43 List-Id: "Use and development of the notmuch mail system."\r
44         <notmuch.notmuchmail.org>\r
45 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
46         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
47 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
48 List-Post: <mailto:notmuch@notmuchmail.org>\r
49 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
50 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
51         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
52 X-List-Received-Date: Tue, 10 Jul 2012 18:57:27 -0000\r
53 \r
54 This patch uses the previously introduced structured format printer in notmuch-search.\r
55 Most of this patch is necessary to keep the text output unchanged. All tests pass, both text and JSON are printed exactly the same as they were before.\r
56 ---\r
57  notmuch-search.c |  275 +++++++++++++++++++++++++++++-------------------------\r
58  1 file changed, 148 insertions(+), 127 deletions(-)\r
59 \r
60 diff --git a/notmuch-search.c b/notmuch-search.c\r
61 index 3be296d..321b32a 100644\r
62 --- a/notmuch-search.c\r
63 +++ b/notmuch-search.c\r
64 @@ -19,6 +19,7 @@\r
65   */\r
66  \r
67  #include "notmuch-client.h"\r
68 +#include "structured-output.h"\r
69  \r
70  typedef enum {\r
71      OUTPUT_SUMMARY,\r
72 @@ -28,6 +29,7 @@ typedef enum {\r
73      OUTPUT_TAGS\r
74  } output_t;\r
75  \r
76 +/* legacy, only needed for non-structured text output */\r
77  typedef struct search_format {\r
78      const char *results_start;\r
79      const char *item_start;\r
80 @@ -64,6 +66,7 @@ format_thread_text (const void *ctx,\r
81                     const int total,\r
82                     const char *authors,\r
83                     const char *subject);\r
84 +\r
85  static const search_format_t format_text = {\r
86      "",\r
87         "",\r
88 @@ -78,35 +81,6 @@ static const search_format_t format_text = {\r
89  };\r
90  \r
91  static void\r
92 -format_item_id_json (const void *ctx,\r
93 -                    const char *item_type,\r
94 -                    const char *item_id);\r
95 -\r
96 -static void\r
97 -format_thread_json (const void *ctx,\r
98 -                   const char *thread_id,\r
99 -                   const time_t date,\r
100 -                   const int matched,\r
101 -                   const int total,\r
102 -                   const char *authors,\r
103 -                   const char *subject);\r
104 -\r
105 -/* Any changes to the JSON format should be reflected in the file\r
106 - * devel/schemata. */\r
107 -static const search_format_t format_json = {\r
108 -    "[",\r
109 -       "{",\r
110 -           format_item_id_json,\r
111 -           format_thread_json,\r
112 -           "\"tags\": [",\r
113 -               "\"%s\"", ", ",\r
114 -           "]", ",\n",\r
115 -       "}",\r
116 -    "]\n",\r
117 -    "]\n",\r
118 -};\r
119 -\r
120 -static void\r
121  format_item_id_text (unused (const void *ctx),\r
122                      const char *item_type,\r
123                      const char *item_id)\r
124 @@ -153,50 +127,9 @@ format_thread_text (const void *ctx,\r
125      talloc_free (ctx_quote);\r
126  }\r
127  \r
128 -static void\r
129 -format_item_id_json (const void *ctx,\r
130 -                    unused (const char *item_type),\r
131 -                    const char *item_id)\r
132 -{\r
133 -    void *ctx_quote = talloc_new (ctx);\r
134 -\r
135 -    printf ("%s", json_quote_str (ctx_quote, item_id));\r
136 -\r
137 -    talloc_free (ctx_quote);\r
138 -    \r
139 -}\r
140 -\r
141 -static void\r
142 -format_thread_json (const void *ctx,\r
143 -                   const char *thread_id,\r
144 -                   const time_t date,\r
145 -                   const int matched,\r
146 -                   const int total,\r
147 -                   const char *authors,\r
148 -                   const char *subject)\r
149 -{\r
150 -    void *ctx_quote = talloc_new (ctx);\r
151 -\r
152 -    printf ("\"thread\": %s,\n"\r
153 -           "\"timestamp\": %ld,\n"\r
154 -           "\"date_relative\": \"%s\",\n"\r
155 -           "\"matched\": %d,\n"\r
156 -           "\"total\": %d,\n"\r
157 -           "\"authors\": %s,\n"\r
158 -           "\"subject\": %s,\n",\r
159 -           json_quote_str (ctx_quote, thread_id),\r
160 -           date,\r
161 -           notmuch_time_relative_date (ctx, date),\r
162 -           matched,\r
163 -           total,\r
164 -           json_quote_str (ctx_quote, authors),\r
165 -           json_quote_str (ctx_quote, subject));\r
166 -\r
167 -    talloc_free (ctx_quote);\r
168 -}\r
169 -\r
170  static int\r
171 -do_search_threads (const search_format_t *format,\r
172 +do_search_threads (const structure_printer_t *format,\r
173 +                  void *state,\r
174                    notmuch_query_t *query,\r
175                    notmuch_sort_t sort,\r
176                    output_t output,\r
177 @@ -209,6 +142,8 @@ do_search_threads (const search_format_t *format,\r
178      time_t date;\r
179      int first_thread = 1;\r
180      int i;\r
181 +    int outermost_level = 0;\r
182 +    int items_level = 0;\r
183  \r
184      if (offset < 0) {\r
185         offset += notmuch_query_count_threads (query);\r
186 @@ -220,7 +155,11 @@ do_search_threads (const search_format_t *format,\r
187      if (threads == NULL)\r
188         return 1;\r
189  \r
190 -    fputs (format->results_start, stdout);\r
191 +    if (format == unstructured_text_printer) {\r
192 +       fputs(format_text.results_start, stdout);\r
193 +    } else { /* structured output */\r
194 +       outermost_level = format->list(state);\r
195 +    }\r
196  \r
197      for (i = 0;\r
198          notmuch_threads_valid (threads) && (limit < 0 || i < offset + limit);\r
199 @@ -235,43 +174,85 @@ do_search_threads (const search_format_t *format,\r
200             continue;\r
201         }\r
202  \r
203 -       if (! first_thread)\r
204 -           fputs (format->item_sep, stdout);\r
205 +       if (format == unstructured_text_printer && ! first_thread)\r
206 +           fputs (format_text.item_sep, stdout);\r
207  \r
208         if (output == OUTPUT_THREADS) {\r
209 -           format->item_id (thread, "thread:",\r
210 -                            notmuch_thread_get_thread_id (thread));\r
211 +           if (format == unstructured_text_printer) {\r
212 +               format_text.item_id (thread, "thread:",\r
213 +                                    notmuch_thread_get_thread_id (thread));\r
214 +           } else { /* structured output */\r
215 +               format->string(state, notmuch_thread_get_thread_id (thread));\r
216 +           }\r
217         } else { /* output == OUTPUT_SUMMARY */\r
218 -           fputs (format->item_start, stdout);\r
219 +\r
220 +           if (format == unstructured_text_printer) {\r
221 +               fputs (format_text.item_start, stdout);\r
222 +           } else { /* structured output */\r
223 +               items_level = format->map(state);\r
224 +           }\r
225  \r
226             if (sort == NOTMUCH_SORT_OLDEST_FIRST)\r
227                 date = notmuch_thread_get_oldest_date (thread);\r
228             else\r
229                 date = notmuch_thread_get_newest_date (thread);\r
230  \r
231 -           format->thread_summary (thread,\r
232 -                                   notmuch_thread_get_thread_id (thread),\r
233 -                                   date,\r
234 -                                   notmuch_thread_get_matched_messages (thread),\r
235 -                                   notmuch_thread_get_total_messages (thread),\r
236 -                                   notmuch_thread_get_authors (thread),\r
237 -                                   notmuch_thread_get_subject (thread));\r
238 -\r
239 -           fputs (format->tag_start, stdout);\r
240 +           if (format == unstructured_text_printer) {\r
241 +               format_text.thread_summary (thread,\r
242 +                                           notmuch_thread_get_thread_id (thread),\r
243 +                                           date,\r
244 +                                           notmuch_thread_get_matched_messages (thread),\r
245 +                                           notmuch_thread_get_total_messages (thread),\r
246 +                                           notmuch_thread_get_authors (thread),\r
247 +                                           notmuch_thread_get_subject (thread));\r
248 +           } else { /* structured output */\r
249 +               void *ctx = talloc_new (0);\r
250 +               format->map_key(state, "thread");\r
251 +               format->string(state, notmuch_thread_get_thread_id (thread));\r
252 +               format->map_key(state, "timestamp");\r
253 +               format->number(state, date);\r
254 +               format->map_key(state, "date_relative");\r
255 +               format->string(state, notmuch_time_relative_date(ctx, date));\r
256 +               format->map_key(state, "matched");\r
257 +               format->number(state, notmuch_thread_get_matched_messages(thread));\r
258 +               format->map_key(state, "total");\r
259 +               format->number(state, notmuch_thread_get_total_messages(thread));\r
260 +               format->map_key(state, "authors");\r
261 +               format->string(state, notmuch_thread_get_authors(thread));\r
262 +               format->map_key(state, "subject");\r
263 +               format->string(state, notmuch_thread_get_subject(thread));\r
264 +               talloc_free(ctx);\r
265 +           };\r
266 +\r
267 +           if (format == unstructured_text_printer) {\r
268 +               fputs (format_text.tag_start, stdout);\r
269 +           } else { /* structured output */\r
270 +               format->map_key(state, "tags");\r
271 +               format->list(state);\r
272 +           }\r
273  \r
274             for (tags = notmuch_thread_get_tags (thread);\r
275                  notmuch_tags_valid (tags);\r
276                  notmuch_tags_move_to_next (tags))\r
277             {\r
278 -               if (! first_tag)\r
279 -                   fputs (format->tag_sep, stdout);\r
280 -               printf (format->tag, notmuch_tags_get (tags));\r
281 +               if (format == unstructured_text_printer && ! first_tag) {\r
282 +                   fputs (format_text.tag_sep, stdout);\r
283 +               }\r
284 +               \r
285 +               if(format == unstructured_text_printer) {\r
286 +                   printf (format_text.tag, notmuch_tags_get (tags));\r
287 +               } else {\r
288 +                   format->string(state, notmuch_tags_get(tags));\r
289 +               }\r
290                 first_tag = 0;\r
291             }\r
292  \r
293 -           fputs (format->tag_end, stdout);\r
294 -\r
295 -           fputs (format->item_end, stdout);\r
296 +           if(format == unstructured_text_printer) {\r
297 +               fputs (format_text.tag_end, stdout);\r
298 +               fputs (format_text.item_end, stdout);\r
299 +           } else { /* structured output */\r
300 +               format->pop(state, items_level);\r
301 +           }\r
302         }\r
303  \r
304         first_thread = 0;\r
305 @@ -279,16 +260,21 @@ do_search_threads (const search_format_t *format,\r
306         notmuch_thread_destroy (thread);\r
307      }\r
308  \r
309 -    if (first_thread)\r
310 -       fputs (format->results_null, stdout);\r
311 -    else\r
312 -       fputs (format->results_end, stdout);\r
313 +    if (format == unstructured_text_printer) {\r
314 +       if (first_thread)\r
315 +           fputs (format_text.results_null, stdout);\r
316 +       else\r
317 +           fputs (format_text.results_end, stdout);\r
318 +    } else { /* structured output */\r
319 +       format->pop(state, outermost_level);\r
320 +    }\r
321  \r
322      return 0;\r
323  }\r
324  \r
325  static int\r
326 -do_search_messages (const search_format_t *format,\r
327 +do_search_messages (const structure_printer_t *format,\r
328 +                   void *state,\r
329                     notmuch_query_t *query,\r
330                     output_t output,\r
331                     int offset,\r
332 @@ -299,6 +285,7 @@ do_search_messages (const search_format_t *format,\r
333      notmuch_filenames_t *filenames;\r
334      int first_message = 1;\r
335      int i;\r
336 +    int outermost_level = 0;\r
337  \r
338      if (offset < 0) {\r
339         offset += notmuch_query_count_messages (query);\r
340 @@ -310,7 +297,11 @@ do_search_messages (const search_format_t *format,\r
341      if (messages == NULL)\r
342         return 1;\r
343  \r
344 -    fputs (format->results_start, stdout);\r
345 +    if(format == unstructured_text_printer) {\r
346 +       fputs (format_text.results_start, stdout);\r
347 +    } else { /* structured output */\r
348 +       outermost_level = format->list(state);\r
349 +    }\r
350  \r
351      for (i = 0;\r
352          notmuch_messages_valid (messages) && (limit < 0 || i < offset + limit);\r
353 @@ -328,11 +319,15 @@ do_search_messages (const search_format_t *format,\r
354                  notmuch_filenames_valid (filenames);\r
355                  notmuch_filenames_move_to_next (filenames))\r
356             {\r
357 -               if (! first_message)\r
358 -                   fputs (format->item_sep, stdout);\r
359 +               if (format == unstructured_text_printer) {\r
360 +                   if (! first_message)\r
361 +                       fputs (format_text.item_sep, stdout);\r
362  \r
363 -               format->item_id (message, "",\r
364 -                                notmuch_filenames_get (filenames));\r
365 +                   format_text.item_id (message, "",\r
366 +                                        notmuch_filenames_get (filenames));\r
367 +               } else { /* structured output */\r
368 +               format->string(state, notmuch_filenames_get (filenames));\r
369 +               }\r
370  \r
371                 first_message = 0;\r
372             }\r
373 @@ -340,11 +335,16 @@ do_search_messages (const search_format_t *format,\r
374             notmuch_filenames_destroy( filenames );\r
375  \r
376         } else { /* output == OUTPUT_MESSAGES */\r
377 -           if (! first_message)\r
378 -               fputs (format->item_sep, stdout);\r
379 +           if (format == unstructured_text_printer) {\r
380 +               if (! first_message)\r
381 +                   fputs (format_text.item_sep, stdout);\r
382 +\r
383 +               format_text.item_id (message, "id:",\r
384 +                                    notmuch_message_get_message_id (message));\r
385 +           } else { /* structured output */\r
386 +               format->string(state, notmuch_message_get_message_id (message));\r
387 +           }\r
388  \r
389 -           format->item_id (message, "id:",\r
390 -                            notmuch_message_get_message_id (message));\r
391             first_message = 0;\r
392         }\r
393  \r
394 @@ -353,23 +353,29 @@ do_search_messages (const search_format_t *format,\r
395  \r
396      notmuch_messages_destroy (messages);\r
397  \r
398 -    if (first_message)\r
399 -       fputs (format->results_null, stdout);\r
400 -    else\r
401 -       fputs (format->results_end, stdout);\r
402 +    if (format == unstructured_text_printer) {\r
403 +       if (first_message)\r
404 +           fputs (format_text.results_null, stdout);\r
405 +       else\r
406 +           fputs (format_text.results_end, stdout);\r
407 +    } else { /* structured output */\r
408 +       format->pop(state, outermost_level);\r
409 +    };\r
410  \r
411      return 0;\r
412  }\r
413  \r
414  static int\r
415  do_search_tags (notmuch_database_t *notmuch,\r
416 -               const search_format_t *format,\r
417 +               const structure_printer_t *format,\r
418 +               void *state,\r
419                 notmuch_query_t *query)\r
420  {\r
421      notmuch_messages_t *messages = NULL;\r
422      notmuch_tags_t *tags;\r
423      const char *tag;\r
424      int first_tag = 1;\r
425 +    int outermost_level = 0;\r
426  \r
427      /* should the following only special case if no excluded terms\r
428       * specified? */\r
429 @@ -387,7 +393,11 @@ do_search_tags (notmuch_database_t *notmuch,\r
430      if (tags == NULL)\r
431         return 1;\r
432  \r
433 -    fputs (format->results_start, stdout);\r
434 +    if (format == unstructured_text_printer) {\r
435 +       fputs (format_text.results_start, stdout);\r
436 +    } else { /* structured output */\r
437 +       outermost_level = format->list(state);\r
438 +    }\r
439  \r
440      for (;\r
441          notmuch_tags_valid (tags);\r
442 @@ -395,10 +405,14 @@ do_search_tags (notmuch_database_t *notmuch,\r
443      {\r
444         tag = notmuch_tags_get (tags);\r
445  \r
446 -       if (! first_tag)\r
447 -           fputs (format->item_sep, stdout);\r
448 -\r
449 -       format->item_id (tags, "", tag);\r
450 +       if (format == unstructured_text_printer) {\r
451 +           if (! first_tag) {\r
452 +               fputs (format_text.item_sep, stdout);\r
453 +           }\r
454 +           format_text.item_id (tags, "", tag);\r
455 +       } else { /* structured output */\r
456 +           format->string(state, tag);\r
457 +       }\r
458  \r
459         first_tag = 0;\r
460      }\r
461 @@ -408,10 +422,14 @@ do_search_tags (notmuch_database_t *notmuch,\r
462      if (messages)\r
463         notmuch_messages_destroy (messages);\r
464  \r
465 -    if (first_tag)\r
466 -       fputs (format->results_null, stdout);\r
467 -    else\r
468 -       fputs (format->results_end, stdout);\r
469 +    if (format == unstructured_text_printer) {\r
470 +       if (first_tag)\r
471 +           fputs (format_text.results_null, stdout);\r
472 +       else\r
473 +           fputs (format_text.results_end, stdout);\r
474 +    } else { /* structured output */\r
475 +       format->pop(state, outermost_level);\r
476 +    };\r
477  \r
478      return 0;\r
479  }\r
480 @@ -430,7 +448,8 @@ notmuch_search_command (void *ctx, int argc, char *argv[])\r
481      notmuch_query_t *query;\r
482      char *query_str;\r
483      notmuch_sort_t sort = NOTMUCH_SORT_NEWEST_FIRST;\r
484 -    const search_format_t *format = &format_text;\r
485 +    const structure_printer_t *format = unstructured_text_printer;\r
486 +    void *state = NULL;\r
487      int opt_index, ret;\r
488      output_t output = OUTPUT_SUMMARY;\r
489      int offset = 0;\r
490 @@ -475,10 +494,12 @@ notmuch_search_command (void *ctx, int argc, char *argv[])\r
491  \r
492      switch (format_sel) {\r
493      case NOTMUCH_FORMAT_TEXT:\r
494 -       format = &format_text;\r
495 +       format = unstructured_text_printer;\r
496 +       state = 0;\r
497         break;\r
498      case NOTMUCH_FORMAT_JSON:\r
499 -       format = &format_json;\r
500 +       format = &json_structure_printer;\r
501 +       state = format->initial_state(format, stdout);\r
502         break;\r
503      }\r
504  \r
505 @@ -532,14 +553,14 @@ notmuch_search_command (void *ctx, int argc, char *argv[])\r
506      default:\r
507      case OUTPUT_SUMMARY:\r
508      case OUTPUT_THREADS:\r
509 -       ret = do_search_threads (format, query, sort, output, offset, limit);\r
510 +       ret = do_search_threads (format, state, query, sort, output, offset, limit);\r
511         break;\r
512      case OUTPUT_MESSAGES:\r
513      case OUTPUT_FILES:\r
514 -       ret = do_search_messages (format, query, output, offset, limit);\r
515 +       ret = do_search_messages (format, state, query, output, offset, limit);\r
516         break;\r
517      case OUTPUT_TAGS:\r
518 -       ret = do_search_tags (notmuch, format, query);\r
519 +       ret = do_search_tags (notmuch, format, state, query);\r
520         break;\r
521      }\r
522  \r
523 -- \r
524 1.7.10.4\r
525 \r