lib: Add support for automatically excluding tags from queries
authorAustin Clements <amdragon@MIT.EDU>
Sun, 15 Jan 2012 00:17:33 +0000 (19:17 -0500)
committerDavid Bremner <bremner@debian.org>
Tue, 17 Jan 2012 01:06:35 +0000 (21:06 -0400)
This is useful for tags like "deleted" and "spam" that people
generally want to exclude from query results.  These exclusions will
be overridden if a tag is explicitly mentioned in a query.

lib/notmuch-private.h
lib/notmuch.h
lib/query.cc

index 60a932fc936324fc39fedb3b736d86aeaa4857e5..7bf153e03fcd1b35bcc697f505e9d6441ecef9c4 100644 (file)
@@ -458,7 +458,7 @@ typedef struct _notmuch_string_node {
     struct _notmuch_string_node *next;
 } notmuch_string_node_t;
 
-typedef struct _notmuch_string_list {
+typedef struct visible _notmuch_string_list {
     int length;
     notmuch_string_node_t *head;
     notmuch_string_node_t **tail;
index 9f23a106e53b7acef19d1bf26036ed6993a361df..7929fe7222ea0bc92d0842a2444d92373a0fc4c9 100644 (file)
@@ -457,6 +457,12 @@ notmuch_query_set_sort (notmuch_query_t *query, notmuch_sort_t sort);
 notmuch_sort_t
 notmuch_query_get_sort (notmuch_query_t *query);
 
+/* Add a tag that will be excluded from the query results by default.
+ * This exclusion will be overridden if this tag appears explicitly in
+ * the query. */
+void
+notmuch_query_add_tag_exclude (notmuch_query_t *query, const char *tag);
+
 /* Execute a query for threads, returning a notmuch_threads_t object
  * which can be used to iterate over the results. The returned threads
  * object is owned by the query and as such, will only be valid until
index b6c0f12d9cd87f73993be6ef6c822319df888995..0b366025ba847314605157e23b193410a792e801 100644 (file)
@@ -27,6 +27,7 @@ struct _notmuch_query {
     notmuch_database_t *notmuch;
     const char *query_string;
     notmuch_sort_t sort;
+    notmuch_string_list_t *exclude_terms;
 };
 
 typedef struct _notmuch_mset_messages {
@@ -76,6 +77,8 @@ notmuch_query_create (notmuch_database_t *notmuch,
 
     query->sort = NOTMUCH_SORT_NEWEST_FIRST;
 
+    query->exclude_terms = _notmuch_string_list_create (query);
+
     return query;
 }
 
@@ -97,6 +100,13 @@ notmuch_query_get_sort (notmuch_query_t *query)
     return query->sort;
 }
 
+void
+notmuch_query_add_tag_exclude (notmuch_query_t *query, const char *tag)
+{
+    char *term = talloc_asprintf (query, "%s%s", _find_prefix ("tag"), tag);
+    _notmuch_string_list_append (query->exclude_terms, term);
+}
+
 /* We end up having to call the destructors explicitly because we had
  * to use "placement new" in order to initialize C++ objects within a
  * block that we allocated with talloc. So C++ is making talloc
@@ -112,6 +122,27 @@ _notmuch_messages_destructor (notmuch_mset_messages_t *messages)
     return 0;
 }
 
+/* Return a query that does not match messages with the excluded tags
+ * registered with the query.  Any tags that explicitly appear in
+ * xquery will not be excluded. */
+static Xapian::Query
+_notmuch_exclude_tags (notmuch_query_t *query, Xapian::Query xquery)
+{
+    for (notmuch_string_node_t *term = query->exclude_terms->head; term;
+        term = term->next) {
+       Xapian::TermIterator it = xquery.get_terms_begin ();
+       Xapian::TermIterator end = xquery.get_terms_end ();
+       for (; it != end; it++) {
+           if ((*it).compare (term->string) == 0)
+               break;
+       }
+       if (it == end)
+           xquery = Xapian::Query (Xapian::Query::OP_AND_NOT,
+                                   xquery, Xapian::Query (term->string));
+    }
+    return xquery;
+}
+
 notmuch_messages_t *
 notmuch_query_search_messages (notmuch_query_t *query)
 {
@@ -157,6 +188,8 @@ notmuch_query_search_messages (notmuch_query_t *query)
                                         mail_query, string_query);
        }
 
+       final_query = _notmuch_exclude_tags (query, final_query);
+
        enquire.set_weighting_scheme (Xapian::BoolWeight());
 
        switch (query->sort) {
@@ -436,6 +469,8 @@ notmuch_query_count_messages (notmuch_query_t *query)
                                         mail_query, string_query);
        }
 
+       final_query = _notmuch_exclude_tags (query, final_query);
+
        enquire.set_weighting_scheme(Xapian::BoolWeight());
        enquire.set_docid_order(Xapian::Enquire::ASCENDING);