unofficial mirror of notmuch@notmuchmail.org
 help / color / mirror / code / Atom feed
* [PATCH] cli: add --output=address-{from,to,all} to notmuch search
  2014-09-05 16:06 [PATCH v1 0/3] Address completion entirely in elisp David Edmondson
@ 2014-09-06  8:14 ` Jani Nikula
  0 siblings, 0 replies; 11+ messages in thread
From: Jani Nikula @ 2014-09-06  8:14 UTC (permalink / raw)
  To: notmuch, David Edmondson, Mark Walters

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

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 1/3] cli: add support for parsing multiple keyword arguments
@ 2014-09-06 12:53 Jani Nikula
  2014-09-06 12:53 ` [PATCH 2/3] cli: add --output=address-{from, to, all} to notmuch search Jani Nikula
                   ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Jani Nikula @ 2014-09-06 12:53 UTC (permalink / raw)
  To: notmuch

This allows having multiple --foo=bar --foo=baz options on the command
line, with the corresponding values OR'd together.
---
 command-line-arguments.c | 6 +++++-
 command-line-arguments.h | 1 +
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/command-line-arguments.c b/command-line-arguments.c
index 844d6c3d18bf..c6f7269603cb 100644
--- a/command-line-arguments.c
+++ b/command-line-arguments.c
@@ -23,7 +23,10 @@ _process_keyword_arg (const notmuch_opt_desc_t *arg_desc, char next, const char
     while (keywords->name) {
 	if (strcmp (arg_str, keywords->name) == 0) {
 	    if (arg_desc->output_var) {
-		*((int *)arg_desc->output_var) = keywords->value;
+		if (arg_desc->opt_type == NOTMUCH_OPT_KEYWORD_FLAGS)
+		    *((int *)arg_desc->output_var) |= keywords->value;
+		else
+		    *((int *)arg_desc->output_var) = keywords->value;
 	    }
 	    return TRUE;
 	}
@@ -152,6 +155,7 @@ parse_option (const char *arg,
 
 	switch (try->opt_type) {
 	case NOTMUCH_OPT_KEYWORD:
+	case NOTMUCH_OPT_KEYWORD_FLAGS:
 	    return _process_keyword_arg (try, next, value);
 	case NOTMUCH_OPT_BOOLEAN:
 	    return _process_boolean_arg (try, next, value);
diff --git a/command-line-arguments.h b/command-line-arguments.h
index de1734ad2fdb..085a4923b5fa 100644
--- a/command-line-arguments.h
+++ b/command-line-arguments.h
@@ -8,6 +8,7 @@ enum notmuch_opt_type {
     NOTMUCH_OPT_BOOLEAN,	/* --verbose              */
     NOTMUCH_OPT_INT,		/* --frob=8               */
     NOTMUCH_OPT_KEYWORD,	/* --format=raw|json|text */
+    NOTMUCH_OPT_KEYWORD_FLAGS,  /* the above with values OR'd together */
     NOTMUCH_OPT_STRING,		/* --file=/tmp/gnarf.txt  */
     NOTMUCH_OPT_POSITION	/* notmuch dump pos_arg   */
 };
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/3] cli: add --output=address-{from, to, all} to notmuch search
  2014-09-06 12:53 [PATCH 1/3] cli: add support for parsing multiple keyword arguments Jani Nikula
@ 2014-09-06 12:53 ` Jani Nikula
  2014-09-06 13:35   ` Mark Walters
  2014-09-06 12:53 ` [PATCH 3/3] cli: deduplicate addresses for --output=address-* Jani Nikula
  2014-09-19 19:27 ` [PATCH 1/3] cli: add support for parsing multiple keyword arguments David Bremner
  2 siblings, 1 reply; 11+ messages in thread
From: Jani Nikula @ 2014-09-06 12:53 UTC (permalink / raw)
  To: notmuch

address-from prints reply-to or from, address-to prints to, cc, and
bcc, and address-all prints all of them.
---
 notmuch-search.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 104 insertions(+), 9 deletions(-)

diff --git a/notmuch-search.c b/notmuch-search.c
index bc9be4593ecc..c84ecc31262c 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -23,11 +23,14 @@
 #include "string-util.h"
 
 typedef enum {
-    OUTPUT_SUMMARY,
-    OUTPUT_THREADS,
-    OUTPUT_MESSAGES,
-    OUTPUT_FILES,
-    OUTPUT_TAGS
+    OUTPUT_SUMMARY	= 1 << 0,
+    OUTPUT_THREADS	= 1 << 1,
+    OUTPUT_MESSAGES	= 1 << 2,
+    OUTPUT_FILES	= 1 << 3,
+    OUTPUT_TAGS		= 1 << 4,
+    OUTPUT_ADDRESS_FROM	= 1 << 5,
+    OUTPUT_ADDRESS_TO	= 1 << 6,
+    OUTPUT_ADDRESS_ALL	= OUTPUT_ADDRESS_FROM | OUTPUT_ADDRESS_TO,
 } output_t;
 
 /* Return two stable query strings that identify exactly the matched
@@ -214,6 +217,66 @@ do_search_threads (sprinter_t *format,
     return 0;
 }
 
+static void
+print_address_list (sprinter_t *format, 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, 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 (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, const char *recipients)
+{
+    InternetAddressList *list;
+
+    if (recipients == NULL)
+	return;
+
+    list = internet_address_list_parse_string (recipients);
+    if (list == NULL)
+	return;
+
+    print_address_list (format, list);
+}
+
 static int
 do_search_messages (sprinter_t *format,
 		    notmuch_query_t *query,
@@ -264,11 +327,33 @@ 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) {
+		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, addrs);
+	    }
+
+	    if (output & OUTPUT_ADDRESS_TO) {
+		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, addrs);
+		}
+	    }
 	}
 
 	notmuch_message_destroy (message);
@@ -338,7 +423,7 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
     notmuch_sort_t sort = NOTMUCH_SORT_NEWEST_FIRST;
     sprinter_t *format = NULL;
     int opt_index, ret;
-    output_t output = OUTPUT_SUMMARY;
+    output_t output = 0;
     int offset = 0;
     int limit = -1; /* unlimited */
     notmuch_exclude_t exclude = NOTMUCH_EXCLUDE_TRUE;
@@ -364,10 +449,12 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
 				  { "text0", NOTMUCH_FORMAT_TEXT0 },
 				  { 0, 0 } } },
 	{ NOTMUCH_OPT_INT, &notmuch_format_version, "format-version", 0, 0 },
-	{ NOTMUCH_OPT_KEYWORD, &output, "output", 'o',
+	{ NOTMUCH_OPT_KEYWORD_FLAGS, &output, "output", 'o',
 	  (notmuch_keyword_t []){ { "summary", OUTPUT_SUMMARY },
 				  { "threads", OUTPUT_THREADS },
 				  { "messages", OUTPUT_MESSAGES },
+				  { "address-from", OUTPUT_ADDRESS_FROM },
+				  { "address-to", OUTPUT_ADDRESS_TO },
 				  { "files", OUTPUT_FILES },
 				  { "tags", OUTPUT_TAGS },
 				  { 0, 0 } } },
@@ -387,6 +474,9 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
     if (opt_index < 0)
 	return EXIT_FAILURE;
 
+    if (! output)
+	output = OUTPUT_SUMMARY;
+
     switch (format_sel) {
     case NOTMUCH_FORMAT_TEXT:
 	format = sprinter_text_create (config, stdout);
@@ -453,18 +543,23 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
     }
 
     switch (output) {
-    default:
     case OUTPUT_SUMMARY:
     case OUTPUT_THREADS:
 	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;
     case OUTPUT_TAGS:
 	ret = do_search_tags (notmuch, format, query);
 	break;
+    default:
+	fprintf (stderr, "Error: the combination of outputs is not supported.\n");
+	ret = 1;
     }
 
     notmuch_query_destroy (query);
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/3] cli: deduplicate addresses for --output=address-*
  2014-09-06 12:53 [PATCH 1/3] cli: add support for parsing multiple keyword arguments Jani Nikula
  2014-09-06 12:53 ` [PATCH 2/3] cli: add --output=address-{from, to, all} to notmuch search Jani Nikula
@ 2014-09-06 12:53 ` Jani Nikula
  2014-09-19 19:27 ` [PATCH 1/3] cli: add support for parsing multiple keyword arguments David Bremner
  2 siblings, 0 replies; 11+ messages in thread
From: Jani Nikula @ 2014-09-06 12:53 UTC (permalink / raw)
  To: notmuch

---
 notmuch-search.c | 32 ++++++++++++++++++++++++++------
 1 file changed, 26 insertions(+), 6 deletions(-)

diff --git a/notmuch-search.c b/notmuch-search.c
index c84ecc31262c..c3ca3246bceb 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -218,7 +218,8 @@ do_search_threads (sprinter_t *format,
 }
 
 static void
-print_address_list (sprinter_t *format, InternetAddressList *list)
+print_address_list (sprinter_t *format, GHashTable *addrs,
+		    InternetAddressList *list)
 {
     InternetAddress *address;
     int i;
@@ -234,7 +235,7 @@ print_address_list (sprinter_t *format, InternetAddressList *list)
 	    if (group_list == NULL)
 		continue;
 
-	    print_address_list (format, group_list);
+	    print_address_list (format, addrs, group_list);
 	} else {
 	    InternetAddressMailbox *mailbox;
 	    const char *name;
@@ -246,6 +247,11 @@ print_address_list (sprinter_t *format, InternetAddressList *list)
 	    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
@@ -263,7 +269,7 @@ print_address_list (sprinter_t *format, InternetAddressList *list)
 }
 
 static void
-print_address_string (sprinter_t *format, const char *recipients)
+print_address_string (sprinter_t *format, GHashTable *addrs, const char *recipients)
 {
     InternetAddressList *list;
 
@@ -274,7 +280,13 @@ print_address_string (sprinter_t *format, const char *recipients)
     if (list == NULL)
 	return;
 
-    print_address_list (format, list);
+    print_address_list (format, addrs, list);
+}
+
+static void
+_my_talloc_free_for_g_hash (void *ptr)
+{
+    talloc_free (ptr);
 }
 
 static int
@@ -288,8 +300,13 @@ 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_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)
@@ -341,7 +358,7 @@ do_search_messages (sprinter_t *format,
 		if (addrs == NULL || *addrs == '\0')
 		    addrs = notmuch_message_get_header (message, "from");
 
-		print_address_string (format, addrs);
+		print_address_string (format, addresses, addrs);
 	    }
 
 	    if (output & OUTPUT_ADDRESS_TO) {
@@ -351,7 +368,7 @@ do_search_messages (sprinter_t *format,
 
 		for (j = 0; j < ARRAY_SIZE (hdrs); j++) {
 		    addrs = notmuch_message_get_header (message, hdrs[j]);
-		    print_address_string (format, addrs);
+		    print_address_string (format, addresses, addrs);
 		}
 	    }
 	}
@@ -359,6 +376,9 @@ do_search_messages (sprinter_t *format,
 	notmuch_message_destroy (message);
     }
 
+    if (addresses)
+	g_hash_table_unref (addresses);
+
     notmuch_messages_destroy (messages);
 
     format->end (format);
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 2/3] cli: add --output=address-{from, to, all} to notmuch search
  2014-09-06 12:53 ` [PATCH 2/3] cli: add --output=address-{from, to, all} to notmuch search Jani Nikula
@ 2014-09-06 13:35   ` Mark Walters
  2014-09-06 16:41     ` [PATCH] cli: add --output=address-{from,to,all} " Jani Nikula
  0 siblings, 1 reply; 11+ messages in thread
From: Mark Walters @ 2014-09-06 13:35 UTC (permalink / raw)
  To: Jani Nikula, notmuch

On Sat, 06 Sep 2014, Jani Nikula <jani@nikula.org> wrote:
> address-from prints reply-to or from, address-to prints to, cc, and
> bcc, and address-all prints all of them.

Hi

I like these: thanks a lot for doing this. 

Just one quick comment before I do an actual review:

> ---
>  notmuch-search.c | 113 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 104 insertions(+), 9 deletions(-)
>
> diff --git a/notmuch-search.c b/notmuch-search.c
> index bc9be4593ecc..c84ecc31262c 100644
> --- a/notmuch-search.c
> +++ b/notmuch-search.c
> @@ -23,11 +23,14 @@
>  #include "string-util.h"
>  
>  typedef enum {
> -    OUTPUT_SUMMARY,
> -    OUTPUT_THREADS,
> -    OUTPUT_MESSAGES,
> -    OUTPUT_FILES,
> -    OUTPUT_TAGS
> +    OUTPUT_SUMMARY	= 1 << 0,
> +    OUTPUT_THREADS	= 1 << 1,
> +    OUTPUT_MESSAGES	= 1 << 2,
> +    OUTPUT_FILES	= 1 << 3,
> +    OUTPUT_TAGS		= 1 << 4,
> +    OUTPUT_ADDRESS_FROM	= 1 << 5,
> +    OUTPUT_ADDRESS_TO	= 1 << 6,
> +    OUTPUT_ADDRESS_ALL	= OUTPUT_ADDRESS_FROM | OUTPUT_ADDRESS_TO,
>  } output_t;
>  
>  /* Return two stable query strings that identify exactly the matched
> @@ -214,6 +217,66 @@ do_search_threads (sprinter_t *format,
>      return 0;
>  }
>  
> +static void
> +print_address_list (sprinter_t *format, 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, 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 (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, const char *recipients)
> +{
> +    InternetAddressList *list;
> +
> +    if (recipients == NULL)
> +	return;
> +
> +    list = internet_address_list_parse_string (recipients);
> +    if (list == NULL)
> +	return;
> +
> +    print_address_list (format, list);
> +}
> +
>  static int
>  do_search_messages (sprinter_t *format,
>  		    notmuch_query_t *query,
> @@ -264,11 +327,33 @@ 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) {
> +		const char *addrs;
> +
> +		addrs = notmuch_message_get_header (message, "reply-to");
> +
> +		if (addrs == NULL || *addrs == '\0')
> +		    addrs = notmuch_message_get_header (message, "from");

I would suggest adding a separate address-reply-to option. The main
reason is that we store from in the database so if you do from without
the reply-to it is *very* fast whereas with the reply-to notmuch has to
read every message to get the reply-to header. Even on a fully hot cache
this means that from alone is  a factor of 10 faster than reply-to/from.

(If anyone wants to test this themselves just comment out the reply-to
and if lines above)

Best wishes

Mark

> +
> +		print_address_string (format, addrs);
> +	    }
> +
> +	    if (output & OUTPUT_ADDRESS_TO) {
> +		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, addrs);
> +		}
> +	    }
>  	}
>  
>  	notmuch_message_destroy (message);
> @@ -338,7 +423,7 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
>      notmuch_sort_t sort = NOTMUCH_SORT_NEWEST_FIRST;
>      sprinter_t *format = NULL;
>      int opt_index, ret;
> -    output_t output = OUTPUT_SUMMARY;
> +    output_t output = 0;
>      int offset = 0;
>      int limit = -1; /* unlimited */
>      notmuch_exclude_t exclude = NOTMUCH_EXCLUDE_TRUE;
> @@ -364,10 +449,12 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
>  				  { "text0", NOTMUCH_FORMAT_TEXT0 },
>  				  { 0, 0 } } },
>  	{ NOTMUCH_OPT_INT, &notmuch_format_version, "format-version", 0, 0 },
> -	{ NOTMUCH_OPT_KEYWORD, &output, "output", 'o',
> +	{ NOTMUCH_OPT_KEYWORD_FLAGS, &output, "output", 'o',
>  	  (notmuch_keyword_t []){ { "summary", OUTPUT_SUMMARY },
>  				  { "threads", OUTPUT_THREADS },
>  				  { "messages", OUTPUT_MESSAGES },
> +				  { "address-from", OUTPUT_ADDRESS_FROM },
> +				  { "address-to", OUTPUT_ADDRESS_TO },
>  				  { "files", OUTPUT_FILES },
>  				  { "tags", OUTPUT_TAGS },
>  				  { 0, 0 } } },
> @@ -387,6 +474,9 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
>      if (opt_index < 0)
>  	return EXIT_FAILURE;
>  
> +    if (! output)
> +	output = OUTPUT_SUMMARY;
> +
>      switch (format_sel) {
>      case NOTMUCH_FORMAT_TEXT:
>  	format = sprinter_text_create (config, stdout);
> @@ -453,18 +543,23 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
>      }
>  
>      switch (output) {
> -    default:
>      case OUTPUT_SUMMARY:
>      case OUTPUT_THREADS:
>  	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;
>      case OUTPUT_TAGS:
>  	ret = do_search_tags (notmuch, format, query);
>  	break;
> +    default:
> +	fprintf (stderr, "Error: the combination of outputs is not supported.\n");
> +	ret = 1;
>      }
>  
>      notmuch_query_destroy (query);
> -- 
> 2.1.0
>
> _______________________________________________
> notmuch mailing list
> notmuch@notmuchmail.org
> http://notmuchmail.org/mailman/listinfo/notmuch

^ permalink raw reply	[flat|nested] 11+ messages in thread

* [PATCH] cli: add --output=address-{from,to,all} to notmuch search
  2014-09-06 13:35   ` Mark Walters
@ 2014-09-06 16:41     ` Jani Nikula
  2014-09-06 16:47       ` [PATCH] cli: add --output=address-{from, to, all} " Jani Nikula
                         ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Jani Nikula @ 2014-09-06 16:41 UTC (permalink / raw)
  To: notmuch

address-from prints reply-to or from, address-to prints to, cc, and
bcc, and address-all prints all of them.
---
 notmuch-search.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 100 insertions(+), 9 deletions(-)

diff --git a/notmuch-search.c b/notmuch-search.c
index bc9be4593ecc..e7cf3d2a0fdf 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -23,11 +23,14 @@
 #include "string-util.h"
 
 typedef enum {
-    OUTPUT_SUMMARY,
-    OUTPUT_THREADS,
-    OUTPUT_MESSAGES,
-    OUTPUT_FILES,
-    OUTPUT_TAGS
+    OUTPUT_SUMMARY	= 1 << 0,
+    OUTPUT_THREADS	= 1 << 1,
+    OUTPUT_MESSAGES	= 1 << 2,
+    OUTPUT_FILES	= 1 << 3,
+    OUTPUT_TAGS		= 1 << 4,
+    OUTPUT_SENDER	= 1 << 5,
+    OUTPUT_RECIPIENTS	= 1 << 6,
+    OUTPUT_ADDRESSES	= OUTPUT_SENDER | OUTPUT_RECIPIENTS,
 } output_t;
 
 /* Return two stable query strings that identify exactly the matched
@@ -214,6 +217,66 @@ do_search_threads (sprinter_t *format,
     return 0;
 }
 
+static void
+print_address_list (sprinter_t *format, 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, 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 (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, const char *recipients)
+{
+    InternetAddressList *list;
+
+    if (recipients == NULL)
+	return;
+
+    list = internet_address_list_parse_string (recipients);
+    if (list == NULL)
+	return;
+
+    print_address_list (format, list);
+}
+
 static int
 do_search_messages (sprinter_t *format,
 		    notmuch_query_t *query,
@@ -264,11 +327,29 @@ 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_SENDER) {
+		const char *addrs;
+
+		addrs = notmuch_message_get_header (message, "from");
+		print_address_string (format, addrs);
+	    }
+
+	    if (output & OUTPUT_RECIPIENTS) {
+		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, addrs);
+		}
+	    }
 	}
 
 	notmuch_message_destroy (message);
@@ -338,7 +419,7 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
     notmuch_sort_t sort = NOTMUCH_SORT_NEWEST_FIRST;
     sprinter_t *format = NULL;
     int opt_index, ret;
-    output_t output = OUTPUT_SUMMARY;
+    output_t output = 0;
     int offset = 0;
     int limit = -1; /* unlimited */
     notmuch_exclude_t exclude = NOTMUCH_EXCLUDE_TRUE;
@@ -364,10 +445,12 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
 				  { "text0", NOTMUCH_FORMAT_TEXT0 },
 				  { 0, 0 } } },
 	{ NOTMUCH_OPT_INT, &notmuch_format_version, "format-version", 0, 0 },
-	{ NOTMUCH_OPT_KEYWORD, &output, "output", 'o',
+	{ NOTMUCH_OPT_KEYWORD_FLAGS, &output, "output", 'o',
 	  (notmuch_keyword_t []){ { "summary", OUTPUT_SUMMARY },
 				  { "threads", OUTPUT_THREADS },
 				  { "messages", OUTPUT_MESSAGES },
+				  { "sender", OUTPUT_SENDER },
+				  { "recipients", OUTPUT_RECIPIENTS },
 				  { "files", OUTPUT_FILES },
 				  { "tags", OUTPUT_TAGS },
 				  { 0, 0 } } },
@@ -387,6 +470,9 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
     if (opt_index < 0)
 	return EXIT_FAILURE;
 
+    if (! output)
+	output = OUTPUT_SUMMARY;
+
     switch (format_sel) {
     case NOTMUCH_FORMAT_TEXT:
 	format = sprinter_text_create (config, stdout);
@@ -453,18 +539,23 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
     }
 
     switch (output) {
-    default:
     case OUTPUT_SUMMARY:
     case OUTPUT_THREADS:
 	ret = do_search_threads (format, query, sort, output, offset, limit);
 	break;
     case OUTPUT_MESSAGES:
+    case OUTPUT_SENDER:
+    case OUTPUT_RECIPIENTS:
+    case OUTPUT_ADDRESSES:
     case OUTPUT_FILES:
 	ret = do_search_messages (format, query, output, offset, limit, dupe);
 	break;
     case OUTPUT_TAGS:
 	ret = do_search_tags (notmuch, format, query);
 	break;
+    default:
+	fprintf (stderr, "Error: the combination of outputs is not supported.\n");
+	ret = 1;
     }
 
     notmuch_query_destroy (query);
-- 
2.1.0

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH] cli: add --output=address-{from, to, all} to notmuch search
  2014-09-06 16:41     ` [PATCH] cli: add --output=address-{from,to,all} " Jani Nikula
@ 2014-09-06 16:47       ` Jani Nikula
  2014-09-06 17:47       ` Mark Walters
  2014-09-19 19:57       ` [PATCH] cli: add --output=address-{from,to,all} " David Bremner
  2 siblings, 0 replies; 11+ messages in thread
From: Jani Nikula @ 2014-09-06 16:47 UTC (permalink / raw)
  To: notmuch

On Sat, 06 Sep 2014, Jani Nikula <jani@nikula.org> wrote:
> address-from prints reply-to or from, address-to prints to, cc, and
> bcc, and address-all prints all of them.

*sigh* this was supposed to be:

---

cli: add --output=sender and --output=recipients to notmuch search
    
sender prints from, recipients prints to, cc, and bcc.

---

I don't have the time for this, and I'm rushing too much...


BR,
Jani.



> ---
>  notmuch-search.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 100 insertions(+), 9 deletions(-)
>
> diff --git a/notmuch-search.c b/notmuch-search.c
> index bc9be4593ecc..e7cf3d2a0fdf 100644
> --- a/notmuch-search.c
> +++ b/notmuch-search.c
> @@ -23,11 +23,14 @@
>  #include "string-util.h"
>  
>  typedef enum {
> -    OUTPUT_SUMMARY,
> -    OUTPUT_THREADS,
> -    OUTPUT_MESSAGES,
> -    OUTPUT_FILES,
> -    OUTPUT_TAGS
> +    OUTPUT_SUMMARY	= 1 << 0,
> +    OUTPUT_THREADS	= 1 << 1,
> +    OUTPUT_MESSAGES	= 1 << 2,
> +    OUTPUT_FILES	= 1 << 3,
> +    OUTPUT_TAGS		= 1 << 4,
> +    OUTPUT_SENDER	= 1 << 5,
> +    OUTPUT_RECIPIENTS	= 1 << 6,
> +    OUTPUT_ADDRESSES	= OUTPUT_SENDER | OUTPUT_RECIPIENTS,
>  } output_t;
>  
>  /* Return two stable query strings that identify exactly the matched
> @@ -214,6 +217,66 @@ do_search_threads (sprinter_t *format,
>      return 0;
>  }
>  
> +static void
> +print_address_list (sprinter_t *format, 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, 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 (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, const char *recipients)
> +{
> +    InternetAddressList *list;
> +
> +    if (recipients == NULL)
> +	return;
> +
> +    list = internet_address_list_parse_string (recipients);
> +    if (list == NULL)
> +	return;
> +
> +    print_address_list (format, list);
> +}
> +
>  static int
>  do_search_messages (sprinter_t *format,
>  		    notmuch_query_t *query,
> @@ -264,11 +327,29 @@ 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_SENDER) {
> +		const char *addrs;
> +
> +		addrs = notmuch_message_get_header (message, "from");
> +		print_address_string (format, addrs);
> +	    }
> +
> +	    if (output & OUTPUT_RECIPIENTS) {
> +		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, addrs);
> +		}
> +	    }
>  	}
>  
>  	notmuch_message_destroy (message);
> @@ -338,7 +419,7 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
>      notmuch_sort_t sort = NOTMUCH_SORT_NEWEST_FIRST;
>      sprinter_t *format = NULL;
>      int opt_index, ret;
> -    output_t output = OUTPUT_SUMMARY;
> +    output_t output = 0;
>      int offset = 0;
>      int limit = -1; /* unlimited */
>      notmuch_exclude_t exclude = NOTMUCH_EXCLUDE_TRUE;
> @@ -364,10 +445,12 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
>  				  { "text0", NOTMUCH_FORMAT_TEXT0 },
>  				  { 0, 0 } } },
>  	{ NOTMUCH_OPT_INT, &notmuch_format_version, "format-version", 0, 0 },
> -	{ NOTMUCH_OPT_KEYWORD, &output, "output", 'o',
> +	{ NOTMUCH_OPT_KEYWORD_FLAGS, &output, "output", 'o',
>  	  (notmuch_keyword_t []){ { "summary", OUTPUT_SUMMARY },
>  				  { "threads", OUTPUT_THREADS },
>  				  { "messages", OUTPUT_MESSAGES },
> +				  { "sender", OUTPUT_SENDER },
> +				  { "recipients", OUTPUT_RECIPIENTS },
>  				  { "files", OUTPUT_FILES },
>  				  { "tags", OUTPUT_TAGS },
>  				  { 0, 0 } } },
> @@ -387,6 +470,9 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
>      if (opt_index < 0)
>  	return EXIT_FAILURE;
>  
> +    if (! output)
> +	output = OUTPUT_SUMMARY;
> +
>      switch (format_sel) {
>      case NOTMUCH_FORMAT_TEXT:
>  	format = sprinter_text_create (config, stdout);
> @@ -453,18 +539,23 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
>      }
>  
>      switch (output) {
> -    default:
>      case OUTPUT_SUMMARY:
>      case OUTPUT_THREADS:
>  	ret = do_search_threads (format, query, sort, output, offset, limit);
>  	break;
>      case OUTPUT_MESSAGES:
> +    case OUTPUT_SENDER:
> +    case OUTPUT_RECIPIENTS:
> +    case OUTPUT_ADDRESSES:
>      case OUTPUT_FILES:
>  	ret = do_search_messages (format, query, output, offset, limit, dupe);
>  	break;
>      case OUTPUT_TAGS:
>  	ret = do_search_tags (notmuch, format, query);
>  	break;
> +    default:
> +	fprintf (stderr, "Error: the combination of outputs is not supported.\n");
> +	ret = 1;
>      }
>  
>      notmuch_query_destroy (query);
> -- 
> 2.1.0

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] cli: add --output=address-{from, to, all} to notmuch search
  2014-09-06 16:41     ` [PATCH] cli: add --output=address-{from,to,all} " Jani Nikula
  2014-09-06 16:47       ` [PATCH] cli: add --output=address-{from, to, all} " Jani Nikula
@ 2014-09-06 17:47       ` Mark Walters
  2014-09-19 19:57       ` [PATCH] cli: add --output=address-{from,to,all} " David Bremner
  2 siblings, 0 replies; 11+ messages in thread
From: Mark Walters @ 2014-09-06 17:47 UTC (permalink / raw)
  To: Jani Nikula, notmuch


On Sat, 06 Sep 2014, Jani Nikula <jani@nikula.org> wrote:
> address-from prints reply-to or from, address-to prints to, cc, and
> bcc, and address-all prints all of them.

This looks good to me. Obviously needs the new commit
message. 

I think we should think  about the deduplication possibilities but that
can be added later. My timings suggest that there is a 20 times speed up
in using this with --output=sender over calling notmuch show
--body=false --entire-thread=false.

If you want the to,cc then this version is only twice as fast as the
notmuch show version. 

(All the above are with a hot cache: I expect bigger improvements with a
cold cache).

So this could well speed up dme's address completion patch
id:1409921969-65129-1-git-send-email-dme@dme.org by a factor of 20.

(The nevermore variants will not get such a big gain as they look at
to/cc rather than from)

Best wishes

Mark


> ---
>  notmuch-search.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++-----
>  1 file changed, 100 insertions(+), 9 deletions(-)
>
> diff --git a/notmuch-search.c b/notmuch-search.c
> index bc9be4593ecc..e7cf3d2a0fdf 100644
> --- a/notmuch-search.c
> +++ b/notmuch-search.c
> @@ -23,11 +23,14 @@
>  #include "string-util.h"
>  
>  typedef enum {
> -    OUTPUT_SUMMARY,
> -    OUTPUT_THREADS,
> -    OUTPUT_MESSAGES,
> -    OUTPUT_FILES,
> -    OUTPUT_TAGS
> +    OUTPUT_SUMMARY	= 1 << 0,
> +    OUTPUT_THREADS	= 1 << 1,
> +    OUTPUT_MESSAGES	= 1 << 2,
> +    OUTPUT_FILES	= 1 << 3,
> +    OUTPUT_TAGS		= 1 << 4,
> +    OUTPUT_SENDER	= 1 << 5,
> +    OUTPUT_RECIPIENTS	= 1 << 6,
> +    OUTPUT_ADDRESSES	= OUTPUT_SENDER | OUTPUT_RECIPIENTS,
>  } output_t;
>  
>  /* Return two stable query strings that identify exactly the matched
> @@ -214,6 +217,66 @@ do_search_threads (sprinter_t *format,
>      return 0;
>  }
>  
> +static void
> +print_address_list (sprinter_t *format, 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, 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 (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, const char *recipients)
> +{
> +    InternetAddressList *list;
> +
> +    if (recipients == NULL)
> +	return;
> +
> +    list = internet_address_list_parse_string (recipients);
> +    if (list == NULL)
> +	return;
> +
> +    print_address_list (format, list);
> +}
> +
>  static int
>  do_search_messages (sprinter_t *format,
>  		    notmuch_query_t *query,
> @@ -264,11 +327,29 @@ 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_SENDER) {
> +		const char *addrs;
> +
> +		addrs = notmuch_message_get_header (message, "from");
> +		print_address_string (format, addrs);
> +	    }
> +
> +	    if (output & OUTPUT_RECIPIENTS) {
> +		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, addrs);
> +		}
> +	    }
>  	}
>  
>  	notmuch_message_destroy (message);
> @@ -338,7 +419,7 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
>      notmuch_sort_t sort = NOTMUCH_SORT_NEWEST_FIRST;
>      sprinter_t *format = NULL;
>      int opt_index, ret;
> -    output_t output = OUTPUT_SUMMARY;
> +    output_t output = 0;
>      int offset = 0;
>      int limit = -1; /* unlimited */
>      notmuch_exclude_t exclude = NOTMUCH_EXCLUDE_TRUE;
> @@ -364,10 +445,12 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
>  				  { "text0", NOTMUCH_FORMAT_TEXT0 },
>  				  { 0, 0 } } },
>  	{ NOTMUCH_OPT_INT, &notmuch_format_version, "format-version", 0, 0 },
> -	{ NOTMUCH_OPT_KEYWORD, &output, "output", 'o',
> +	{ NOTMUCH_OPT_KEYWORD_FLAGS, &output, "output", 'o',
>  	  (notmuch_keyword_t []){ { "summary", OUTPUT_SUMMARY },
>  				  { "threads", OUTPUT_THREADS },
>  				  { "messages", OUTPUT_MESSAGES },
> +				  { "sender", OUTPUT_SENDER },
> +				  { "recipients", OUTPUT_RECIPIENTS },
>  				  { "files", OUTPUT_FILES },
>  				  { "tags", OUTPUT_TAGS },
>  				  { 0, 0 } } },
> @@ -387,6 +470,9 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
>      if (opt_index < 0)
>  	return EXIT_FAILURE;
>  
> +    if (! output)
> +	output = OUTPUT_SUMMARY;
> +
>      switch (format_sel) {
>      case NOTMUCH_FORMAT_TEXT:
>  	format = sprinter_text_create (config, stdout);
> @@ -453,18 +539,23 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
>      }
>  
>      switch (output) {
> -    default:
>      case OUTPUT_SUMMARY:
>      case OUTPUT_THREADS:
>  	ret = do_search_threads (format, query, sort, output, offset, limit);
>  	break;
>      case OUTPUT_MESSAGES:
> +    case OUTPUT_SENDER:
> +    case OUTPUT_RECIPIENTS:
> +    case OUTPUT_ADDRESSES:
>      case OUTPUT_FILES:
>  	ret = do_search_messages (format, query, output, offset, limit, dupe);
>  	break;
>      case OUTPUT_TAGS:
>  	ret = do_search_tags (notmuch, format, query);
>  	break;
> +    default:
> +	fprintf (stderr, "Error: the combination of outputs is not supported.\n");
> +	ret = 1;
>      }
>  
>      notmuch_query_destroy (query);
> -- 
> 2.1.0
>
> _______________________________________________
> notmuch mailing list
> notmuch@notmuchmail.org
> http://notmuchmail.org/mailman/listinfo/notmuch

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/3] cli: add support for parsing multiple keyword arguments
  2014-09-06 12:53 [PATCH 1/3] cli: add support for parsing multiple keyword arguments Jani Nikula
  2014-09-06 12:53 ` [PATCH 2/3] cli: add --output=address-{from, to, all} to notmuch search Jani Nikula
  2014-09-06 12:53 ` [PATCH 3/3] cli: deduplicate addresses for --output=address-* Jani Nikula
@ 2014-09-19 19:27 ` David Bremner
  2 siblings, 0 replies; 11+ messages in thread
From: David Bremner @ 2014-09-19 19:27 UTC (permalink / raw)
  To: Jani Nikula, notmuch

Jani Nikula <jani@nikula.org> writes:

> This allows having multiple --foo=bar --foo=baz options on the command
> line, with the corresponding values OR'd together.
> ---

This looks OK. In hindsight I guess we could have had only keyword_flags
from the beginning, but I guess that would be pretty intrusive to change
at this point.

d

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] cli: add --output=address-{from,to,all} to notmuch search
  2014-09-06 16:41     ` [PATCH] cli: add --output=address-{from,to,all} " Jani Nikula
  2014-09-06 16:47       ` [PATCH] cli: add --output=address-{from, to, all} " Jani Nikula
  2014-09-06 17:47       ` Mark Walters
@ 2014-09-19 19:57       ` David Bremner
  2014-09-20  8:04         ` [PATCH] cli: add --output=address-{from, to, all} " Michal Sojka
  2 siblings, 1 reply; 11+ messages in thread
From: David Bremner @ 2014-09-19 19:57 UTC (permalink / raw)
  To: Jani Nikula, notmuch

Jani Nikula <jani@nikula.org> writes:

> +	    if (name && *name)
> +		full_address = talloc_asprintf (NULL, "%s <%s>", name, addr);
> +	    else
> +		full_address = talloc_asprintf (NULL, "<%s>", addr

Is there some reason not to use sprinter as a talloc context here?

> +
> +	    if (!full_address)
> +		break;

Is the error here out of memory? Maybe an error message would be a good
idea.


Obviously the docs need to be updated as well, and ideally the tests.  I
think Jani was hinting that he didn't want to be the person to do
that. Any volunteers?

d

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH] cli: add --output=address-{from, to, all} to notmuch search
  2014-09-19 19:57       ` [PATCH] cli: add --output=address-{from,to,all} " David Bremner
@ 2014-09-20  8:04         ` Michal Sojka
  0 siblings, 0 replies; 11+ messages in thread
From: Michal Sojka @ 2014-09-20  8:04 UTC (permalink / raw)
  To: David Bremner, Jani Nikula, notmuch

On Fri, Sep 19 2014, David Bremner wrote:
> Jani Nikula <jani@nikula.org> writes:
>
>> +	    if (name && *name)
>> +		full_address = talloc_asprintf (NULL, "%s <%s>", name, addr);
>> +	    else
>> +		full_address = talloc_asprintf (NULL, "<%s>", addr
>
> Is there some reason not to use sprinter as a talloc context here?
>
>> +
>> +	    if (!full_address)
>> +		break;
>
> Is the error here out of memory? Maybe an error message would be a good
> idea.
>
>
> Obviously the docs need to be updated as well, and ideally the tests.  I
> think Jani was hinting that he didn't want to be the person to do
> that. Any volunteers?

Yes, I'll look at that. It will probably take me a few days.

-Michal

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2014-09-20  8:04 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-06 12:53 [PATCH 1/3] cli: add support for parsing multiple keyword arguments Jani Nikula
2014-09-06 12:53 ` [PATCH 2/3] cli: add --output=address-{from, to, all} to notmuch search Jani Nikula
2014-09-06 13:35   ` Mark Walters
2014-09-06 16:41     ` [PATCH] cli: add --output=address-{from,to,all} " Jani Nikula
2014-09-06 16:47       ` [PATCH] cli: add --output=address-{from, to, all} " Jani Nikula
2014-09-06 17:47       ` Mark Walters
2014-09-19 19:57       ` [PATCH] cli: add --output=address-{from,to,all} " David Bremner
2014-09-20  8:04         ` [PATCH] cli: add --output=address-{from, to, all} " Michal Sojka
2014-09-06 12:53 ` [PATCH 3/3] cli: deduplicate addresses for --output=address-* Jani Nikula
2014-09-19 19:27 ` [PATCH 1/3] cli: add support for parsing multiple keyword arguments David Bremner
  -- strict thread matches above, loose matches on Subject: below --
2014-09-05 16:06 [PATCH v1 0/3] Address completion entirely in elisp David Edmondson
2014-09-06  8:14 ` [PATCH] cli: add --output=address-{from,to,all} to notmuch search Jani Nikula

Code repositories for project(s) associated with this public inbox

	https://yhetil.org/notmuch.git/

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).