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
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
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
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
35 Date: Tue, 10 Jul 2012 20:57:23 +0200
\r
36 Message-ID: <87wr2btpf0.fsf@nexoid.at>
\r
38 Content-Type: text/plain
\r
40 X-BeenThere: notmuch@notmuchmail.org
\r
41 X-Mailman-Version: 2.1.13
\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
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
57 notmuch-search.c | 275 +++++++++++++++++++++++++++++-------------------------
\r
58 1 file changed, 148 insertions(+), 127 deletions(-)
\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
67 #include "notmuch-client.h"
\r
68 +#include "structured-output.h"
\r
72 @@ -28,6 +29,7 @@ typedef enum {
\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
82 const char *authors,
\r
83 const char *subject);
\r
85 static const search_format_t format_text = {
\r
88 @@ -78,35 +81,6 @@ static const search_format_t format_text = {
\r
92 -format_item_id_json (const void *ctx,
\r
93 - const char *item_type,
\r
94 - const char *item_id);
\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
102 - const char *authors,
\r
103 - const char *subject);
\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
110 - format_item_id_json,
\r
111 - format_thread_json,
\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
129 -format_item_id_json (const void *ctx,
\r
130 - unused (const char *item_type),
\r
131 - const char *item_id)
\r
133 - void *ctx_quote = talloc_new (ctx);
\r
135 - printf ("%s", json_quote_str (ctx_quote, item_id));
\r
137 - talloc_free (ctx_quote);
\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
147 - const char *authors,
\r
148 - const char *subject)
\r
150 - void *ctx_quote = talloc_new (ctx);
\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
161 - notmuch_time_relative_date (ctx, date),
\r
164 - json_quote_str (ctx_quote, authors),
\r
165 - json_quote_str (ctx_quote, subject));
\r
167 - talloc_free (ctx_quote);
\r
171 -do_search_threads (const search_format_t *format,
\r
172 +do_search_threads (const structure_printer_t *format,
\r
174 notmuch_query_t *query,
\r
175 notmuch_sort_t sort,
\r
177 @@ -209,6 +142,8 @@ do_search_threads (const search_format_t *format,
\r
179 int first_thread = 1;
\r
181 + int outermost_level = 0;
\r
182 + int items_level = 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
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
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
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
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
217 } else { /* output == OUTPUT_SUMMARY */
\r
218 - fputs (format->item_start, stdout);
\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
226 if (sort == NOTMUCH_SORT_OLDEST_FIRST)
\r
227 date = notmuch_thread_get_oldest_date (thread);
\r
229 date = notmuch_thread_get_newest_date (thread);
\r
231 - format->thread_summary (thread,
\r
232 - notmuch_thread_get_thread_id (thread),
\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
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
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
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
274 for (tags = notmuch_thread_get_tags (thread);
\r
275 notmuch_tags_valid (tags);
\r
276 notmuch_tags_move_to_next (tags))
\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
285 + if(format == unstructured_text_printer) {
\r
286 + printf (format_text.tag, notmuch_tags_get (tags));
\r
288 + format->string(state, notmuch_tags_get(tags));
\r
293 - fputs (format->tag_end, stdout);
\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
305 @@ -279,16 +260,21 @@ do_search_threads (const search_format_t *format,
\r
306 notmuch_thread_destroy (thread);
\r
309 - if (first_thread)
\r
310 - fputs (format->results_null, stdout);
\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
317 + fputs (format_text.results_end, stdout);
\r
318 + } else { /* structured output */
\r
319 + format->pop(state, outermost_level);
\r
326 -do_search_messages (const search_format_t *format,
\r
327 +do_search_messages (const structure_printer_t *format,
\r
329 notmuch_query_t *query,
\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
336 + int outermost_level = 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
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
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
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
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
373 @@ -340,11 +335,16 @@ do_search_messages (const search_format_t *format,
\r
374 notmuch_filenames_destroy( filenames );
\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
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
389 - format->item_id (message, "id:",
\r
390 - notmuch_message_get_message_id (message));
\r
394 @@ -353,23 +353,29 @@ do_search_messages (const search_format_t *format,
\r
396 notmuch_messages_destroy (messages);
\r
398 - if (first_message)
\r
399 - fputs (format->results_null, stdout);
\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
406 + fputs (format_text.results_end, stdout);
\r
407 + } else { /* structured output */
\r
408 + format->pop(state, outermost_level);
\r
415 do_search_tags (notmuch_database_t *notmuch,
\r
416 - const search_format_t *format,
\r
417 + const structure_printer_t *format,
\r
419 notmuch_query_t *query)
\r
421 notmuch_messages_t *messages = NULL;
\r
422 notmuch_tags_t *tags;
\r
425 + int outermost_level = 0;
\r
427 /* should the following only special case if no excluded terms
\r
429 @@ -387,7 +393,11 @@ do_search_tags (notmuch_database_t *notmuch,
\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
441 notmuch_tags_valid (tags);
\r
442 @@ -395,10 +405,14 @@ do_search_tags (notmuch_database_t *notmuch,
\r
444 tag = notmuch_tags_get (tags);
\r
447 - fputs (format->item_sep, stdout);
\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
454 + format_text.item_id (tags, "", tag);
\r
455 + } else { /* structured output */
\r
456 + format->string(state, tag);
\r
461 @@ -408,10 +422,14 @@ do_search_tags (notmuch_database_t *notmuch,
\r
463 notmuch_messages_destroy (messages);
\r
466 - fputs (format->results_null, stdout);
\r
468 - fputs (format->results_end, stdout);
\r
469 + if (format == unstructured_text_printer) {
\r
471 + fputs (format_text.results_null, stdout);
\r
473 + fputs (format_text.results_end, stdout);
\r
474 + } else { /* structured output */
\r
475 + format->pop(state, outermost_level);
\r
480 @@ -430,7 +448,8 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
\r
481 notmuch_query_t *query;
\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
490 @@ -475,10 +494,12 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
\r
492 switch (format_sel) {
\r
493 case NOTMUCH_FORMAT_TEXT:
\r
494 - format = &format_text;
\r
495 + format = unstructured_text_printer;
\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
505 @@ -532,14 +553,14 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
\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
512 case OUTPUT_MESSAGES:
\r
514 - ret = do_search_messages (format, query, output, offset, limit);
\r
515 + ret = do_search_messages (format, state, query, output, offset, limit);
\r
518 - ret = do_search_tags (notmuch, format, query);
\r
519 + ret = do_search_tags (notmuch, format, state, query);
\r