[PATCH v3 3/3] Use the JSON structure printer in notmuch-search.
craven at gmx.net
craven at gmx.net
Wed Jul 11 01:26:35 PDT 2012
This patch uses the JSON structure printer for notmuch search. The
changes necessary for switching to the structure printer are minor, a
large part of this patch is concerned with keeping the normal
unstructured text output.
---
notmuch-search.c | 278 ++++++++++++++++++++++++++++++-------------------------
1 file changed, 150 insertions(+), 128 deletions(-)
diff --git a/notmuch-search.c b/notmuch-search.c
index 3be296d..84e4cbc 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -19,6 +19,7 @@
*/
#include "notmuch-client.h"
+#include "structured-output.h"
typedef enum {
OUTPUT_SUMMARY,
@@ -28,6 +29,7 @@ typedef enum {
OUTPUT_TAGS
} output_t;
+/* legacy, only needed for non-structured text output */
typedef struct search_format {
const char *results_start;
const char *item_start;
@@ -64,6 +66,7 @@ format_thread_text (const void *ctx,
const int total,
const char *authors,
const char *subject);
+
static const search_format_t format_text = {
"",
"",
@@ -78,35 +81,6 @@ static const search_format_t format_text = {
};
static void
-format_item_id_json (const void *ctx,
- const char *item_type,
- const char *item_id);
-
-static void
-format_thread_json (const void *ctx,
- const char *thread_id,
- const time_t date,
- const int matched,
- const int total,
- const char *authors,
- const char *subject);
-
-/* Any changes to the JSON format should be reflected in the file
- * devel/schemata. */
-static const search_format_t format_json = {
- "[",
- "{",
- format_item_id_json,
- format_thread_json,
- "\"tags\": [",
- "\"%s\"", ", ",
- "]", ",\n",
- "}",
- "]\n",
- "]\n",
-};
-
-static void
format_item_id_text (unused (const void *ctx),
const char *item_type,
const char *item_id)
@@ -153,50 +127,9 @@ format_thread_text (const void *ctx,
talloc_free (ctx_quote);
}
-static void
-format_item_id_json (const void *ctx,
- unused (const char *item_type),
- const char *item_id)
-{
- void *ctx_quote = talloc_new (ctx);
-
- printf ("%s", json_quote_str (ctx_quote, item_id));
-
- talloc_free (ctx_quote);
-
-}
-
-static void
-format_thread_json (const void *ctx,
- const char *thread_id,
- const time_t date,
- const int matched,
- const int total,
- const char *authors,
- const char *subject)
-{
- void *ctx_quote = talloc_new (ctx);
-
- printf ("\"thread\": %s,\n"
- "\"timestamp\": %ld,\n"
- "\"date_relative\": \"%s\",\n"
- "\"matched\": %d,\n"
- "\"total\": %d,\n"
- "\"authors\": %s,\n"
- "\"subject\": %s,\n",
- json_quote_str (ctx_quote, thread_id),
- date,
- notmuch_time_relative_date (ctx, date),
- matched,
- total,
- json_quote_str (ctx_quote, authors),
- json_quote_str (ctx_quote, subject));
-
- talloc_free (ctx_quote);
-}
-
static int
-do_search_threads (const search_format_t *format,
+do_search_threads (const structure_printer_t *format,
+ void *state,
notmuch_query_t *query,
notmuch_sort_t sort,
output_t output,
@@ -209,6 +142,8 @@ do_search_threads (const search_format_t *format,
time_t date;
int first_thread = 1;
int i;
+ int outermost_level = 0;
+ int items_level = 0;
if (offset < 0) {
offset += notmuch_query_count_threads (query);
@@ -220,7 +155,11 @@ do_search_threads (const search_format_t *format,
if (threads == NULL)
return 1;
- fputs (format->results_start, stdout);
+ if (format == unstructured_text_printer) {
+ fputs(format_text.results_start, stdout);
+ } else { /* structured output */
+ outermost_level = format->list(state);
+ }
for (i = 0;
notmuch_threads_valid (threads) && (limit < 0 || i < offset + limit);
@@ -235,43 +174,85 @@ do_search_threads (const search_format_t *format,
continue;
}
- if (! first_thread)
- fputs (format->item_sep, stdout);
+ if (format == unstructured_text_printer && ! first_thread)
+ fputs (format_text.item_sep, stdout);
if (output == OUTPUT_THREADS) {
- format->item_id (thread, "thread:",
- notmuch_thread_get_thread_id (thread));
+ if (format == unstructured_text_printer) {
+ format_text.item_id (thread, "thread:",
+ notmuch_thread_get_thread_id (thread));
+ } else { /* structured output */
+ format->string(state, notmuch_thread_get_thread_id (thread));
+ }
} else { /* output == OUTPUT_SUMMARY */
- fputs (format->item_start, stdout);
+
+ if (format == unstructured_text_printer) {
+ fputs (format_text.item_start, stdout);
+ } else { /* structured output */
+ items_level = format->map(state);
+ }
if (sort == NOTMUCH_SORT_OLDEST_FIRST)
date = notmuch_thread_get_oldest_date (thread);
else
date = notmuch_thread_get_newest_date (thread);
- format->thread_summary (thread,
- notmuch_thread_get_thread_id (thread),
- date,
- notmuch_thread_get_matched_messages (thread),
- notmuch_thread_get_total_messages (thread),
- notmuch_thread_get_authors (thread),
- notmuch_thread_get_subject (thread));
-
- fputs (format->tag_start, stdout);
+ if (format == unstructured_text_printer) {
+ format_text.thread_summary (thread,
+ notmuch_thread_get_thread_id (thread),
+ date,
+ notmuch_thread_get_matched_messages (thread),
+ notmuch_thread_get_total_messages (thread),
+ notmuch_thread_get_authors (thread),
+ notmuch_thread_get_subject (thread));
+ } else { /* structured output */
+ void *ctx = talloc_new (0);
+ format->map_key(state, "thread");
+ format->string(state, notmuch_thread_get_thread_id (thread));
+ format->map_key(state, "timestamp");
+ format->number(state, date);
+ format->map_key(state, "date_relative");
+ format->string(state, notmuch_time_relative_date(ctx, date));
+ format->map_key(state, "matched");
+ format->number(state, notmuch_thread_get_matched_messages(thread));
+ format->map_key(state, "total");
+ format->number(state, notmuch_thread_get_total_messages(thread));
+ format->map_key(state, "authors");
+ format->string(state, notmuch_thread_get_authors(thread));
+ format->map_key(state, "subject");
+ format->string(state, notmuch_thread_get_subject(thread));
+ talloc_free(ctx);
+ };
+
+ if (format == unstructured_text_printer) {
+ fputs (format_text.tag_start, stdout);
+ } else { /* structured output */
+ format->map_key(state, "tags");
+ format->list(state);
+ }
for (tags = notmuch_thread_get_tags (thread);
notmuch_tags_valid (tags);
notmuch_tags_move_to_next (tags))
{
- if (! first_tag)
- fputs (format->tag_sep, stdout);
- printf (format->tag, notmuch_tags_get (tags));
+ if (format == unstructured_text_printer && ! first_tag) {
+ fputs (format_text.tag_sep, stdout);
+ }
+
+ if(format == unstructured_text_printer) {
+ printf (format_text.tag, notmuch_tags_get (tags));
+ } else {
+ format->string(state, notmuch_tags_get(tags));
+ }
first_tag = 0;
}
- fputs (format->tag_end, stdout);
-
- fputs (format->item_end, stdout);
+ if(format == unstructured_text_printer) {
+ fputs (format_text.tag_end, stdout);
+ fputs (format_text.item_end, stdout);
+ } else { /* structured output */
+ format->pop(state, items_level);
+ }
}
first_thread = 0;
@@ -279,16 +260,21 @@ do_search_threads (const search_format_t *format,
notmuch_thread_destroy (thread);
}
- if (first_thread)
- fputs (format->results_null, stdout);
- else
- fputs (format->results_end, stdout);
+ if (format == unstructured_text_printer) {
+ if (first_thread)
+ fputs (format_text.results_null, stdout);
+ else
+ fputs (format_text.results_end, stdout);
+ } else { /* structured output */
+ format->pop(state, outermost_level);
+ }
return 0;
}
static int
-do_search_messages (const search_format_t *format,
+do_search_messages (const structure_printer_t *format,
+ void *state,
notmuch_query_t *query,
output_t output,
int offset,
@@ -299,6 +285,7 @@ do_search_messages (const search_format_t *format,
notmuch_filenames_t *filenames;
int first_message = 1;
int i;
+ int outermost_level = 0;
if (offset < 0) {
offset += notmuch_query_count_messages (query);
@@ -310,7 +297,11 @@ do_search_messages (const search_format_t *format,
if (messages == NULL)
return 1;
- fputs (format->results_start, stdout);
+ if(format == unstructured_text_printer) {
+ fputs (format_text.results_start, stdout);
+ } else { /* structured output */
+ outermost_level = format->list(state);
+ }
for (i = 0;
notmuch_messages_valid (messages) && (limit < 0 || i < offset + limit);
@@ -328,23 +319,32 @@ do_search_messages (const search_format_t *format,
notmuch_filenames_valid (filenames);
notmuch_filenames_move_to_next (filenames))
{
- if (! first_message)
- fputs (format->item_sep, stdout);
+ if (format == unstructured_text_printer) {
+ if (! first_message)
+ fputs (format_text.item_sep, stdout);
- format->item_id (message, "",
- notmuch_filenames_get (filenames));
+ format_text.item_id (message, "",
+ notmuch_filenames_get (filenames));
+ } else { /* structured output */
+ format->string(state, notmuch_filenames_get (filenames));
+ }
first_message = 0;
}
-
+
notmuch_filenames_destroy( filenames );
} else { /* output == OUTPUT_MESSAGES */
- if (! first_message)
- fputs (format->item_sep, stdout);
+ if (format == unstructured_text_printer) {
+ if (! first_message)
+ fputs (format_text.item_sep, stdout);
+
+ format_text.item_id (message, "id:",
+ notmuch_message_get_message_id (message));
+ } else { /* structured output */
+ format->string(state, notmuch_message_get_message_id (message));
+ }
- format->item_id (message, "id:",
- notmuch_message_get_message_id (message));
first_message = 0;
}
@@ -353,23 +353,29 @@ do_search_messages (const search_format_t *format,
notmuch_messages_destroy (messages);
- if (first_message)
- fputs (format->results_null, stdout);
- else
- fputs (format->results_end, stdout);
+ if (format == unstructured_text_printer) {
+ if (first_message)
+ fputs (format_text.results_null, stdout);
+ else
+ fputs (format_text.results_end, stdout);
+ } else { /* structured output */
+ format->pop(state, outermost_level);
+ };
return 0;
}
static int
do_search_tags (notmuch_database_t *notmuch,
- const search_format_t *format,
+ const structure_printer_t *format,
+ void *state,
notmuch_query_t *query)
{
notmuch_messages_t *messages = NULL;
notmuch_tags_t *tags;
const char *tag;
int first_tag = 1;
+ int outermost_level = 0;
/* should the following only special case if no excluded terms
* specified? */
@@ -387,7 +393,11 @@ do_search_tags (notmuch_database_t *notmuch,
if (tags == NULL)
return 1;
- fputs (format->results_start, stdout);
+ if (format == unstructured_text_printer) {
+ fputs (format_text.results_start, stdout);
+ } else { /* structured output */
+ outermost_level = format->list(state);
+ }
for (;
notmuch_tags_valid (tags);
@@ -395,10 +405,14 @@ do_search_tags (notmuch_database_t *notmuch,
{
tag = notmuch_tags_get (tags);
- if (! first_tag)
- fputs (format->item_sep, stdout);
-
- format->item_id (tags, "", tag);
+ if (format == unstructured_text_printer) {
+ if (! first_tag) {
+ fputs (format_text.item_sep, stdout);
+ }
+ format_text.item_id (tags, "", tag);
+ } else { /* structured output */
+ format->string(state, tag);
+ }
first_tag = 0;
}
@@ -408,10 +422,14 @@ do_search_tags (notmuch_database_t *notmuch,
if (messages)
notmuch_messages_destroy (messages);
- if (first_tag)
- fputs (format->results_null, stdout);
- else
- fputs (format->results_end, stdout);
+ if (format == unstructured_text_printer) {
+ if (first_tag)
+ fputs (format_text.results_null, stdout);
+ else
+ fputs (format_text.results_end, stdout);
+ } else { /* structured output */
+ format->pop(state, outermost_level);
+ };
return 0;
}
@@ -430,7 +448,8 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
notmuch_query_t *query;
char *query_str;
notmuch_sort_t sort = NOTMUCH_SORT_NEWEST_FIRST;
- const search_format_t *format = &format_text;
+ const structure_printer_t *format = unstructured_text_printer;
+ void *state = NULL;
int opt_index, ret;
output_t output = OUTPUT_SUMMARY;
int offset = 0;
@@ -475,13 +494,16 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
switch (format_sel) {
case NOTMUCH_FORMAT_TEXT:
- format = &format_text;
+ format = unstructured_text_printer;
break;
case NOTMUCH_FORMAT_JSON:
- format = &format_json;
+ format = &json_structure_printer;
break;
}
+ if(format != unstructured_text_printer)
+ state = format->initial_state(format, stdout);
+
config = notmuch_config_open (ctx, NULL, NULL);
if (config == NULL)
return 1;
@@ -532,14 +554,14 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
default:
case OUTPUT_SUMMARY:
case OUTPUT_THREADS:
- ret = do_search_threads (format, query, sort, output, offset, limit);
+ ret = do_search_threads (format, state, query, sort, output, offset, limit);
break;
case OUTPUT_MESSAGES:
case OUTPUT_FILES:
- ret = do_search_messages (format, query, output, offset, limit);
+ ret = do_search_messages (format, state, query, output, offset, limit);
break;
case OUTPUT_TAGS:
- ret = do_search_tags (notmuch, format, query);
+ ret = do_search_tags (notmuch, format, state, query);
break;
}
--
1.7.11.1
More information about the notmuch
mailing list