notmuch search: Print the number of matched/total messages for each thread.
authorCarl Worth <cworth@cworth.org>
Fri, 13 Nov 2009 06:01:44 +0000 (22:01 -0800)
committerCarl Worth <cworth@cworth.org>
Fri, 13 Nov 2009 06:01:44 +0000 (22:01 -0800)
Note that we don't print the number of *unread* messages, but instead
the number of messages that matched the search terms. This is in
keeping with our philosophy that the inbox is nothing more than a
search view. If we search for messages with an inbox tag, then that's
what we'll get a count of. (And if somebody does want to see unread
counts, then they can search for the "unread" tag.)

Getting the number of matched messages is really nice when doing
historical searches. For example in a search like:

notmuch search tag:sent

(where the "sent" tag has been applied to all messages originating
from the user's email address)---here it's really nice to be able to
see a thread where the user just mentioned one point [1/13] vs. really
getting involved in the discussion [10/29].

lib/notmuch-private.h
lib/notmuch.h
lib/query.cc
lib/thread.cc
notmuch-search.c

index 190d30385ba3893dcf6d38bd57f938ca81741d6d..c286aa4bcdce2d8821b96d4294e141312013da74 100644 (file)
@@ -150,9 +150,10 @@ _find_prefix (const char *name);
 /* thread.cc */
 
 notmuch_thread_t *
-_notmuch_thread_create (const void *ctx,
+_notmuch_thread_create (void *ctx,
                        notmuch_database_t *notmuch,
-                       const char *thread_id);
+                       const char *thread_id,
+                       const char *query_string);
 
 /* message.cc */
 
index c67376ebd2b0fdeef2016c53b7537f9c253ca282..6469744df36251294fd62d0ba9e4cd1b07224b51 100644 (file)
@@ -469,6 +469,23 @@ notmuch_threads_destroy (notmuch_threads_t *threads);
 const char *
 notmuch_thread_get_thread_id (notmuch_thread_t *thread);
 
+/* Get the total number of messages in 'thread'.
+ *
+ * This count consists of all messages in the database belonging to
+ * this thread. Contrast with notmuch_thread_get_matched_messages() .
+ */
+int
+notmuch_thread_get_total_messages (notmuch_thread_t *thread);
+
+/* Get the number of messages in 'thread' that matched the search.
+ *
+ * This count includes only the messages in this thread that were
+ * matched by the search from which the thread was created. Contrast
+ * with notmuch_thread_get_total_messages() .
+ */
+int
+notmuch_thread_get_matched_messages (notmuch_thread_t *thread);
+
 /* Get the authors of 'thread'
  *
  * The returned string is a comma-separated list of the names of the
index b5f1546ac084d609b24a25a60dd68e677f513145..e853d4ec8e46b55b260fc0264b1756bf59eb26a1 100644 (file)
@@ -220,7 +220,8 @@ notmuch_query_search_threads (notmuch_query_t *query,
            {
                if (threads_seen >= first) {
                    thread = _notmuch_thread_create (query, query->notmuch,
-                                                    thread_id);
+                                                    thread_id,
+                                                    query->query_string);
                    g_ptr_array_add (threads->threads, thread);
                } else {
                    thread = NULL;
index 4f0696b4fc01b8ee13b3fc1af49e3ac03b0bdcb1..df1d0db7fae0ac0f4e8d8f6c400d31dc09b2b3b6 100644 (file)
@@ -34,7 +34,8 @@ struct _notmuch_thread {
     char *authors;
     GHashTable *tags;
 
-    notmuch_bool_t has_message;
+    int total_messages;
+    int matched_messages;
     time_t oldest;
     time_t newest;
 };
@@ -112,49 +113,57 @@ _thread_add_message (notmuch_thread_t *thread,
 
     date = notmuch_message_get_date (message);
 
-    if (date < thread->oldest || ! thread->has_message)
+    if (date < thread->oldest || ! thread->total_messages)
        thread->oldest = date;
 
-    if (date > thread->newest || ! thread->has_message)
+    if (date > thread->newest || ! thread->total_messages)
        thread->newest = date;
 
-    thread->has_message = 1;
+    thread->total_messages++;
 }
 
-/* Create a new notmuch_thread_t object for the given thread ID.
+/* Create a new notmuch_thread_t object for the given thread ID,
+ * treating any messages matching 'query_string' as "matched".
  *
- * Creating the thread will trigger a database search for the messages
- * belonging to the thread so that the thread object can return some
- * details about them, (authors, subject, etc.).
+ * Creating the thread will trigger two database searches. The first
+ * is for all messages belonging to the thread, (to get the first
+ * subject line, the total count of messages, and all authors). The
+ * second search is for all messages that are in the thread and that
+ * also match the given query_string. This is to allow for a separate
+ * count of matched messages, and to allow a viewer to diplay these
+ * messages differently.
  *
- * Here, 'talloc owner' is an optional talloc context to which the new
- * thread will belong. This allows for the caller to not bother
- * calling notmuch_thread_destroy on the thread, and know that all
- * memory will be reclaimed with 'talloc_owner' is freed. The caller
- * still can call notmuch_thread_destroy when finished with the
- * thread if desired.
- *
- * The 'talloc_owner' argument can also be NULL, in which case the
- * caller *is* responsible for calling notmuch_thread_destroy.
+ * Here, 'ctx' is talloc context for the resulting thread object.
  *
  * This function returns NULL in the case of any error.
  */
 notmuch_thread_t *
-_notmuch_thread_create (const void *ctx,
+_notmuch_thread_create (void *ctx,
                        notmuch_database_t *notmuch,
-                       const char *thread_id)
+                       const char *thread_id,
+                       const char *query_string)
 {
     notmuch_thread_t *thread;
-    const char *query_string;
-    notmuch_query_t *query;
+    const char *thread_id_query_string, *matched_query_string;
+    notmuch_query_t *thread_id_query, *matched_query;
     notmuch_messages_t *messages;
 
-    query_string = talloc_asprintf (ctx, "thread:%s", thread_id);
+    thread_id_query_string = talloc_asprintf (ctx, "thread:%s", thread_id);
     if (unlikely (query_string == NULL))
        return NULL;
 
-    query = notmuch_query_create (notmuch, query_string);
-    if (unlikely (query == NULL))
+    matched_query_string = talloc_asprintf (ctx, "%s AND (%s)",
+                                           thread_id_query_string,
+                                           query_string);
+    if (unlikely (matched_query_string == NULL))
+       return NULL;
+
+    thread_id_query = notmuch_query_create (notmuch, thread_id_query_string);
+    if (unlikely (thread_id_query == NULL))
+       return NULL;
+
+    matched_query = notmuch_query_create (notmuch, matched_query_string);
+    if (unlikely (thread_id_query == NULL))
        return NULL;
 
     thread = talloc (ctx, notmuch_thread_t);
@@ -172,20 +181,30 @@ _notmuch_thread_create (const void *ctx,
     thread->tags = g_hash_table_new_full (g_str_hash, g_str_equal,
                                          free, NULL);
 
-    thread->has_message = 0;
+    thread->total_messages = 0;
+    thread->matched_messages = 0;
     thread->oldest = 0;
     thread->newest = 0;
 
-    notmuch_query_set_sort (query, NOTMUCH_SORT_DATE_OLDEST_FIRST);
+    notmuch_query_set_sort (thread_id_query, NOTMUCH_SORT_DATE_OLDEST_FIRST);
 
-    for (messages = notmuch_query_search_messages (query, 0, -1);
+    for (messages = notmuch_query_search_messages (thread_id_query, 0, -1);
         notmuch_messages_has_more (messages);
         notmuch_messages_advance (messages))
     {
        _thread_add_message (thread, notmuch_messages_get (messages));
     }
 
-    notmuch_query_destroy (query);
+    notmuch_query_destroy (thread_id_query);
+
+    for (messages = notmuch_query_search_messages (matched_query, 0, -1);
+        notmuch_messages_has_more (messages);
+        notmuch_messages_advance (messages))
+    {
+       thread->matched_messages++;
+    }
+
+    notmuch_query_destroy (matched_query);
 
     return thread;
 }
@@ -196,6 +215,18 @@ notmuch_thread_get_thread_id (notmuch_thread_t *thread)
     return thread->thread_id;
 }
 
+int
+notmuch_thread_get_total_messages (notmuch_thread_t *thread)
+{
+    return thread->total_messages;
+}
+
+int
+notmuch_thread_get_matched_messages (notmuch_thread_t *thread)
+{
+    return thread->matched_messages;
+}
+
 const char *
 notmuch_thread_get_authors (notmuch_thread_t *thread)
 {
index 85f3514ee099b4142097dde4cd1e0895c979c3af..a0a71bbd7992e02e4f3b42b1bf55939fac0bdc64 100644 (file)
@@ -91,9 +91,11 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
        date = notmuch_thread_get_oldest_date (thread);
        relative_date = notmuch_time_relative_date (ctx, date);
 
-       printf ("thread:%s %12s %s; %s",
+       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));