Add notmuch_thread_get_tags

And augment "notmuch search" to print tag values as well as thread ID
values. This tool is almost usable now.
This commit is contained in:
Carl Worth 2009-10-26 14:46:14 -07:00
parent ef3ab5781a
commit 94f01d9de9
5 changed files with 128 additions and 24 deletions

View file

@ -144,6 +144,9 @@ _notmuch_thread_create (const void *talloc_owner,
notmuch_database_t *notmuch, notmuch_database_t *notmuch,
const char *thread_id); const char *thread_id);
void
_notmuch_thread_add_tag (notmuch_thread_t *thread, const char *tag);
/* message.cc */ /* message.cc */
notmuch_message_t * notmuch_message_t *

View file

@ -610,6 +610,7 @@ search_command (int argc, char *argv[])
notmuch_query_t *query; notmuch_query_t *query;
notmuch_thread_results_t *results; notmuch_thread_results_t *results;
notmuch_thread_t *thread; notmuch_thread_t *thread;
notmuch_tags_t *tags;
char *query_str; char *query_str;
int i; int i;
notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS; notmuch_status_t ret = NOTMUCH_STATUS_SUCCESS;
@ -641,9 +642,23 @@ search_command (int argc, char *argv[])
notmuch_thread_results_has_more (results); notmuch_thread_results_has_more (results);
notmuch_thread_results_advance (results)) notmuch_thread_results_advance (results))
{ {
int first = 1;
thread = notmuch_thread_results_get (results); thread = notmuch_thread_results_get (results);
printf ("%s\n", notmuch_thread_get_thread_id (thread)); printf ("%s (", notmuch_thread_get_thread_id (thread));
for (tags = notmuch_thread_get_tags (thread);
notmuch_tags_has_more (tags);
notmuch_tags_advance (tags))
{
if (! first)
printf (" ");
printf ("%s", notmuch_tags_get (tags));
first = 0;
}
printf (")\n");
notmuch_thread_destroy (thread); notmuch_thread_destroy (thread);
} }

View file

@ -458,6 +458,45 @@ notmuch_thread_results_destroy (notmuch_thread_results_t *results);
const char * const char *
notmuch_thread_get_thread_id (notmuch_thread_t *thread); notmuch_thread_get_thread_id (notmuch_thread_t *thread);
/* Get the tags for 'thread', returning a notmuch_tags_t object which
* can be used to iterate over all tags.
*
* Note: In the Notmuch database, tags are stored on individual
* messages, not on threads. So the tags returned here will be all
* tags of the messages which matched the search and which belong to
* this thread.
*
* The tags object is owned by the thread and as such, will only be
* valid for as long as the thread is valid, (for example, until
* notmuch_thread_destroy or until the query from which it derived is
* destroyed).
*
* Typical usage might be:
*
* notmuch_thread_t *thread;
* notmuch_tags_t *tags;
* const char *tag;
*
* thread = notmuch_thread_results_get (thread_results);
*
* for (tags = notmuch_thread_get_tags (thread);
* notmuch_tags_has_more (tags);
* notmuch_result_advance (tags))
* {
* tag = notmuch_tags_get (tags);
* ....
* }
*
* notmuch_thread_destroy (thread);
*
* Note that there's no explicit destructor needed for the
* notmuch_tags_t object. (For consistency, we do provide a
* notmuch_tags_destroy function, but there's no good reason to call
* it if the message is about to be destroyed).
*/
notmuch_tags_t *
notmuch_thread_get_tags (notmuch_thread_t *thread);
/* Destroy a notmuch_thread_t object. */ /* Destroy a notmuch_thread_t object. */
void void
notmuch_thread_destroy (notmuch_thread_t *thread); notmuch_thread_destroy (notmuch_thread_t *thread);

View file

@ -39,7 +39,7 @@ struct _notmuch_message_results {
struct _notmuch_thread_results { struct _notmuch_thread_results {
notmuch_database_t *notmuch; notmuch_database_t *notmuch;
GPtrArray *thread_ids; GPtrArray *threads;
unsigned int index; unsigned int index;
}; };
@ -165,7 +165,7 @@ notmuch_query_search_messages (notmuch_query_t *query)
static int static int
_notmuch_thread_results_destructor (notmuch_thread_results_t *results) _notmuch_thread_results_destructor (notmuch_thread_results_t *results)
{ {
g_ptr_array_free (results->thread_ids, TRUE); g_ptr_array_free (results->threads, TRUE);
return 0; return 0;
} }
@ -174,9 +174,12 @@ notmuch_thread_results_t *
notmuch_query_search_threads (notmuch_query_t *query) notmuch_query_search_threads (notmuch_query_t *query)
{ {
notmuch_thread_results_t *thread_results; notmuch_thread_results_t *thread_results;
notmuch_thread_t *thread;
const char *thread_id;
notmuch_message_results_t *message_results; notmuch_message_results_t *message_results;
notmuch_message_t *message; notmuch_message_t *message;
const char *thread_id; notmuch_tags_t *tags;
const char *tag;
GHashTable *seen; GHashTable *seen;
thread_results = talloc (query, notmuch_thread_results_t); thread_results = talloc (query, notmuch_thread_results_t);
@ -184,7 +187,7 @@ notmuch_query_search_threads (notmuch_query_t *query)
return NULL; return NULL;
thread_results->notmuch = query->notmuch; thread_results->notmuch = query->notmuch;
thread_results->thread_ids = g_ptr_array_new (); thread_results->threads = g_ptr_array_new ();
thread_results->index = 0; thread_results->index = 0;
talloc_set_destructor (thread_results, _notmuch_thread_results_destructor); talloc_set_destructor (thread_results, _notmuch_thread_results_destructor);
@ -197,18 +200,28 @@ notmuch_query_search_threads (notmuch_query_t *query)
notmuch_message_results_advance (message_results)) notmuch_message_results_advance (message_results))
{ {
message = notmuch_message_results_get (message_results); message = notmuch_message_results_get (message_results);
thread_id = notmuch_message_get_thread_id (message); thread_id = notmuch_message_get_thread_id (message);
if (g_hash_table_lookup_extended (seen, if (! g_hash_table_lookup_extended (seen,
thread_id, NULL, NULL)) thread_id, NULL,
(void **) &thread))
{ {
continue; thread = _notmuch_thread_create (query, query->notmuch,
thread_id);
g_hash_table_insert (seen, xstrdup (thread_id), thread);
g_ptr_array_add (thread_results->threads, thread);
} }
g_hash_table_insert (seen, xstrdup (thread_id), NULL); for (tags = notmuch_message_get_tags (message);
notmuch_tags_has_more (tags);
g_ptr_array_add (thread_results->thread_ids, notmuch_tags_advance (tags))
talloc_strdup (thread_results, thread_id)); {
tag = notmuch_tags_get (tags);
_notmuch_thread_add_tag (thread, tag);
}
} }
g_hash_table_unref (seen); g_hash_table_unref (seen);
@ -268,26 +281,17 @@ notmuch_message_results_destroy (notmuch_message_results_t *results)
notmuch_bool_t notmuch_bool_t
notmuch_thread_results_has_more (notmuch_thread_results_t *results) notmuch_thread_results_has_more (notmuch_thread_results_t *results)
{ {
return (results->index < results->thread_ids->len); return (results->index < results->threads->len);
} }
notmuch_thread_t * notmuch_thread_t *
notmuch_thread_results_get (notmuch_thread_results_t *results) notmuch_thread_results_get (notmuch_thread_results_t *results)
{ {
notmuch_thread_t *thread;
const char *thread_id;
if (! notmuch_thread_results_has_more (results)) if (! notmuch_thread_results_has_more (results))
return NULL; return NULL;
thread_id = (const char *) g_ptr_array_index (results->thread_ids, return (notmuch_thread_t *) g_ptr_array_index (results->threads,
results->index); results->index);
thread = _notmuch_thread_create (results,
results->notmuch,
thread_id);
return thread;
} }
void void

View file

@ -23,11 +23,22 @@
#include <xapian.h> #include <xapian.h>
#include <glib.h> /* GHashTable */
struct _notmuch_thread { struct _notmuch_thread {
notmuch_database_t *notmuch; notmuch_database_t *notmuch;
char *thread_id; char *thread_id;
GHashTable *tags;
}; };
static int
_notmuch_thread_destructor (notmuch_thread_t *thread)
{
g_hash_table_unref (thread->tags);
return 0;
}
/* Create a new notmuch_thread_t object for an existing document in /* Create a new notmuch_thread_t object for an existing document in
* the database. * the database.
* *
@ -54,8 +65,12 @@ _notmuch_thread_create (const void *talloc_owner,
if (unlikely (thread == NULL)) if (unlikely (thread == NULL))
return NULL; return NULL;
talloc_set_destructor (thread, _notmuch_thread_destructor);
thread->notmuch = notmuch; thread->notmuch = notmuch;
thread->thread_id = talloc_strdup (thread, thread_id); thread->thread_id = talloc_strdup (thread, thread_id);
thread->tags = g_hash_table_new_full (g_str_hash, g_str_equal,
free, NULL);
return thread; return thread;
} }
@ -66,6 +81,34 @@ notmuch_thread_get_thread_id (notmuch_thread_t *thread)
return thread->thread_id; return thread->thread_id;
} }
void
_notmuch_thread_add_tag (notmuch_thread_t *thread, const char *tag)
{
g_hash_table_insert (thread->tags, xstrdup (tag), NULL);
}
notmuch_tags_t *
notmuch_thread_get_tags (notmuch_thread_t *thread)
{
notmuch_tags_t *tags;
GList *keys, *l;
tags = _notmuch_tags_create (thread);
if (unlikely (tags == NULL))
return NULL;
keys = g_hash_table_get_keys (thread->tags);
for (l = keys; l; l = l->next)
_notmuch_tags_add_tag (tags, (char *) l->data);
g_list_free (keys);
_notmuch_tags_prepare_iterator (tags);
return tags;
}
void void
notmuch_thread_destroy (notmuch_thread_t *thread) notmuch_thread_destroy (notmuch_thread_t *thread)
{ {