[PATCH] cli: add --output=address-{from,to,all} to notmuch search
Jani Nikula
jani at nikula.org
Sat Sep 6 01:14:27 PDT 2014
address-from prints reply-to or from, address-to prints to, cc, and
bcc, and address-all prints all of them.
---
Mark, David -
I wrote most of this almost two years ago, but wasn't really happy
with it. There's address deduplication, but for large result sets that
might use lots of memory. Maybe the --duplicate option could be
overloaded for doing or not doing deduplication. I'd like to have some
way of picking the prettiest (that's subjective too) name part to go
with the address, now it's just the first encountered. And so on.
But maybe this will be useful for you, and you can pick some ideas. I
won't have the time to do much on this.
Cheers,
Jani.
---
notmuch-search.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 113 insertions(+), 1 deletion(-)
diff --git a/notmuch-search.c b/notmuch-search.c
index bc9be4593ecc..33da90eaceec 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -26,6 +26,9 @@ typedef enum {
OUTPUT_SUMMARY,
OUTPUT_THREADS,
OUTPUT_MESSAGES,
+ OUTPUT_ADDRESS_FROM,
+ OUTPUT_ADDRESS_TO,
+ OUTPUT_ADDRESS_ALL,
OUTPUT_FILES,
OUTPUT_TAGS
} output_t;
@@ -214,6 +217,78 @@ do_search_threads (sprinter_t *format,
return 0;
}
+static void
+print_address_list (sprinter_t *format, GHashTable *addrs,
+ InternetAddressList *list)
+{
+ InternetAddress *address;
+ int i;
+
+ for (i = 0; i < internet_address_list_length (list); i++) {
+ address = internet_address_list_get_address (list, i);
+ if (INTERNET_ADDRESS_IS_GROUP (address)) {
+ InternetAddressGroup *group;
+ InternetAddressList *group_list;
+
+ group = INTERNET_ADDRESS_GROUP (address);
+ group_list = internet_address_group_get_members (group);
+ if (group_list == NULL)
+ continue;
+
+ print_address_list (format, addrs, group_list);
+ } else {
+ InternetAddressMailbox *mailbox;
+ const char *name;
+ const char *addr;
+ char *full_address;
+
+ mailbox = INTERNET_ADDRESS_MAILBOX (address);
+
+ name = internet_address_get_name (address);
+ addr = internet_address_mailbox_get_addr (mailbox);
+
+ if (g_hash_table_lookup_extended (addrs, addr, NULL, NULL))
+ continue;
+
+ g_hash_table_insert (addrs, talloc_strdup (NULL, addr), NULL);
+
+ if (name && *name)
+ full_address = talloc_asprintf (NULL, "%s <%s>", name, addr);
+ else
+ full_address = talloc_asprintf (NULL, "<%s>", addr);
+
+ if (!full_address)
+ break;
+
+ format->string (format, full_address);
+ format->separator (format);
+
+ talloc_free (full_address);
+ }
+ }
+}
+
+static void
+print_address_string (sprinter_t *format, GHashTable *addrs, const char *recipients)
+{
+ InternetAddressList *list;
+
+ if (recipients == NULL)
+ return;
+
+ list = internet_address_list_parse_string (recipients);
+ if (list == NULL)
+ return;
+
+ print_address_list (format, addrs, list);
+}
+
+static void
+_my_talloc_free_for_g_hash (void *ptr)
+{
+ talloc_free (ptr);
+}
+
static int
do_search_messages (sprinter_t *format,
notmuch_query_t *query,
@@ -225,8 +300,14 @@ do_search_messages (sprinter_t *format,
notmuch_message_t *message;
notmuch_messages_t *messages;
notmuch_filenames_t *filenames;
+ GHashTable *addresses = NULL;
int i;
+ if (output == OUTPUT_ADDRESS_FROM || output == OUTPUT_ADDRESS_TO ||
+ output == OUTPUT_ADDRESS_ALL)
+ addresses = g_hash_table_new_full (g_str_hash, g_str_equal,
+ _my_talloc_free_for_g_hash, NULL);
+
if (offset < 0) {
offset += notmuch_query_count_messages (query);
if (offset < 0)
@@ -264,16 +345,41 @@ do_search_messages (sprinter_t *format,
notmuch_filenames_destroy( filenames );
- } else { /* output == OUTPUT_MESSAGES */
+ } else if (output == OUTPUT_MESSAGES) {
format->set_prefix (format, "id");
format->string (format,
notmuch_message_get_message_id (message));
format->separator (format);
+ } else {
+ if (output == OUTPUT_ADDRESS_FROM || output == OUTPUT_ADDRESS_ALL) {
+ const char *addrs;
+
+ addrs = notmuch_message_get_header (message, "reply-to");
+
+ if (addrs == NULL || *addrs == '\0')
+ addrs = notmuch_message_get_header (message, "from");
+
+ print_address_string (format, addresses, addrs);
+ }
+
+ if (output == OUTPUT_ADDRESS_TO || output == OUTPUT_ADDRESS_ALL) {
+ const char *hdrs[] = { "to", "cc", "bcc" };
+ const char *addrs;
+ size_t j;
+
+ for (j = 0; j < ARRAY_SIZE (hdrs); j++) {
+ addrs = notmuch_message_get_header (message, hdrs[j]);
+ print_address_string (format, addresses, addrs);
+ }
+ }
}
notmuch_message_destroy (message);
}
+ if (addresses)
+ g_hash_table_unref (addresses);
+
notmuch_messages_destroy (messages);
format->end (format);
@@ -368,6 +474,9 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
(notmuch_keyword_t []){ { "summary", OUTPUT_SUMMARY },
{ "threads", OUTPUT_THREADS },
{ "messages", OUTPUT_MESSAGES },
+ { "address-from", OUTPUT_ADDRESS_FROM },
+ { "address-to", OUTPUT_ADDRESS_TO },
+ { "address-all", OUTPUT_ADDRESS_ALL },
{ "files", OUTPUT_FILES },
{ "tags", OUTPUT_TAGS },
{ 0, 0 } } },
@@ -459,6 +568,9 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
ret = do_search_threads (format, query, sort, output, offset, limit);
break;
case OUTPUT_MESSAGES:
+ case OUTPUT_ADDRESS_FROM:
+ case OUTPUT_ADDRESS_TO:
+ case OUTPUT_ADDRESS_ALL:
case OUTPUT_FILES:
ret = do_search_messages (format, query, output, offset, limit, dupe);
break;
--
2.1.0
More information about the notmuch
mailing list