aboutsummaryrefslogtreecommitdiffhomepage
path: root/notmuch-search.c
diff options
context:
space:
mode:
authorGravatar Scott Robinson <scott@quadhome.com>2009-12-31 11:17:40 -0400
committerGravatar Carl Worth <cworth@cworth.org>2010-02-23 12:01:12 -0800
commit6ce2bf68f53fec4302121763e588c33c7cd86a9c (patch)
tree97eed1a84956f582cc43efbb16419c43b930c242 /notmuch-search.c
parent3ca7a4fbcc9cd72330bce1b1670150af1e250006 (diff)
Add an "--format=(json|text)" command-line option to both notmuch-search and notmuch-show.
In the case of notmuch-show, "--format=json" also implies "--entire-thread" as the thread structure is implicit in the emitted document tree. As a coincidence to the implementation, multipart message ID numbers are now incremented with each part printed. This changes the previous semantics, which were unclear and not necessary related to the actual ordering of the message parts.
Diffstat (limited to 'notmuch-search.c')
-rw-r--r--notmuch-search.c163
1 files changed, 149 insertions, 14 deletions
diff --git a/notmuch-search.c b/notmuch-search.c
index dc44eb66..482c6e8e 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -20,8 +20,120 @@
#include "notmuch-client.h"
+typedef struct search_format {
+ const char *results_start;
+ const char *thread_start;
+ void (*thread) (const void *ctx,
+ const char *id,
+ const time_t date,
+ const int matched,
+ const int total,
+ const char *authors,
+ const char *subject);
+ const char *tag_start;
+ const char *tag;
+ const char *tag_sep;
+ const char *tag_end;
+ const char *thread_sep;
+ const char *thread_end;
+ const char *results_end;
+} search_format_t;
+
+static void
+format_thread_text (const void *ctx,
+ const char *id,
+ const time_t date,
+ const int matched,
+ const int total,
+ const char *authors,
+ const char *subject);
+static const search_format_t format_text = {
+ "",
+ "",
+ format_thread_text,
+ " (",
+ "%s", " ",
+ ")", "",
+ "\n",
+ "",
+};
+
+static void
+format_thread_json (const void *ctx,
+ const char *id,
+ const time_t date,
+ const int matched,
+ const int total,
+ const char *authors,
+ const char *subject);
+static const search_format_t format_json = {
+ "[",
+ "{",
+ format_thread_json,
+ "\"tags\": [",
+ "\"%s\"", ", ",
+ "]", ",\n",
+ "}",
+ "]\n",
+};
+
+static void
+format_thread_text (const void *ctx,
+ const char *id,
+ const time_t date,
+ const int matched,
+ const int total,
+ const char *authors,
+ const char *subject)
+{
+ printf ("thread:%s %12s [%d/%d] %s; %s",
+ id,
+ notmuch_time_relative_date (ctx, date),
+ matched,
+ total,
+ authors,
+ subject);
+}
+
+static void
+format_thread_json (const void *ctx,
+ const char *id,
+ const time_t date,
+ const int matched,
+ const int total,
+ const char *authors,
+ const char *subject)
+{
+ struct tm *tm;
+ char timestamp[40];
+ void *ctx_quote = talloc_new (ctx);
+
+ tm = gmtime (&date);
+ if (tm == NULL)
+ INTERNAL_ERROR ("gmtime failed on thread %s.", id);
+
+ if (strftime (timestamp, sizeof (timestamp), "%s", tm) == 0)
+ INTERNAL_ERROR ("strftime failed on thread %s.", id);
+
+ printf ("\"id\": %s,\n"
+ "\"timestamp\": %s,\n"
+ "\"matched\": %d,\n"
+ "\"total\": %d,\n"
+ "\"authors\": %s,\n"
+ "\"subject\": %s,\n",
+ json_quote_str (ctx_quote, id),
+ timestamp,
+ matched,
+ total,
+ json_quote_str (ctx_quote, authors),
+ json_quote_str (ctx_quote, subject));
+
+ talloc_free (ctx_quote);
+}
+
static void
do_search_threads (const void *ctx,
+ const search_format_t *format,
notmuch_query_t *query,
notmuch_sort_t sort)
{
@@ -29,7 +141,9 @@ do_search_threads (const void *ctx,
notmuch_threads_t *threads;
notmuch_tags_t *tags;
time_t date;
- const char *relative_date;
+ int first_thread = 1;
+
+ fputs (format->results_start, stdout);
for (threads = notmuch_query_search_threads (query);
notmuch_threads_has_more (threads);
@@ -37,6 +151,9 @@ do_search_threads (const void *ctx,
{
int first_tag = 1;
+ if (! first_thread)
+ fputs (format->thread_sep, stdout);
+
thread = notmuch_threads_get (threads);
if (sort == NOTMUCH_SORT_OLDEST_FIRST)
@@ -44,30 +161,37 @@ do_search_threads (const void *ctx,
else
date = notmuch_thread_get_newest_date (thread);
- relative_date = notmuch_time_relative_date (ctx, date);
+ fputs (format->thread_start, stdout);
+
+ format->thread (ctx,
+ 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));
- printf ("thread:%s %12s [%d/%d] %s; %s",
- notmuch_thread_get_thread_id (thread),
- relative_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);
- printf (" (");
for (tags = notmuch_thread_get_tags (thread);
notmuch_tags_has_more (tags);
notmuch_tags_advance (tags))
{
if (! first_tag)
- printf (" ");
- printf ("%s", notmuch_tags_get (tags));
+ fputs (format->tag_sep, stdout);
+ printf (format->tag, notmuch_tags_get (tags));
first_tag = 0;
}
- printf (")\n");
+
+ fputs (format->tag_end, stdout);
+ fputs (format->thread_end, stdout);
+
+ first_thread = 0;
notmuch_thread_destroy (thread);
}
+
+ fputs (format->results_end, stdout);
}
int
@@ -79,6 +203,7 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
char *query_str;
char *opt;
notmuch_sort_t sort = NOTMUCH_SORT_NEWEST_FIRST;
+ const search_format_t *format = &format_text;
int i;
for (i = 0; i < argc && argv[i][0] == '-'; i++) {
@@ -96,6 +221,16 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
fprintf (stderr, "Invalid value for --sort: %s\n", opt);
return 1;
}
+ } else if (STRNCMP_LITERAL (argv[i], "--format=") == 0) {
+ opt = argv[i] + sizeof ("--format=") - 1;
+ if (strcmp (opt, "text") == 0) {
+ format = &format_text;
+ } else if (strcmp (opt, "json") == 0) {
+ format = &format_json;
+ } else {
+ fprintf (stderr, "Invalid value for --format: %s\n", opt);
+ return 1;
+ }
} else {
fprintf (stderr, "Unrecognized option: %s\n", argv[i]);
return 1;
@@ -132,7 +267,7 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
notmuch_query_set_sort (query, sort);
- do_search_threads (ctx, query, sort);
+ do_search_threads (ctx, format, query, sort);
notmuch_query_destroy (query);
notmuch_database_close (notmuch);