* [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, ¬much_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
* 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, ¬much_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, ¬much_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, ¬much_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, ¬much_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] 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
* [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 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 v1 0/3] Address completion entirely in elisp. @ 2014-09-05 16:06 David Edmondson 2014-09-06 8:14 ` [PATCH] cli: add --output=address-{from,to,all} to notmuch search Jani Nikula 0 siblings, 1 reply; 11+ messages in thread From: David Edmondson @ 2014-09-05 16:06 UTC (permalink / raw) To: Mark Walters, notmuch On Fri, Sep 05 2014, Mark Walters wrote: > On Fri, 05 Sep 2014, David Edmondson <dme@dme.org> wrote: >> Address completion entirely in elisp. >> >> I grew frustrated with having to use an external command to provide >> address completion, as they all had annoyances (up front scanning, >> requiring python bindings, etc.). This is an attempt to provide >> something similar to jkr's notmuch-addresses.py (which I was >> previously using) entirely in elisp, relying only on the `notmuch' >> command. > > Just a few quick comments: the first is relevant to others trying this > patch. > > 1) You seem to be missing a (require 'std11) somewhere. I did this via M-: > and then it ran fine. My apologies. Will fix (and a compiler warning at the same time). > 2) It is not quick on a spinning rust disk. This may not be relevant as > the delay is probably notmuch so would also be the case if I were using > notmuch-addresses.py (i normally just use a trivial script that parses > my .mailrc) It's not always as fast as I would like on SSD either :-) The mechanism is very similar to the equivalent Python program, so I think that it's probably about the same. > 3) Have you tried > id:1407771091-12651-1-git-send-email-sojkam1@fel.cvut.cz and do you have > any comments on the comparison? No, I will dig it out and look. > 4) Finally, I wonder if we would be worth approaching the backend > notmuch use slightly differently: if we added a > notmuch_messages_collect_from function which was very similar to > notmuch_messages_collect_tags, and added a corresponding --output=from > to notmuch search then you would get the information you need very > quickly. I think it might be a lot faster as I think the from header is > stored in the database but some other headers are not, so that the > current method the show --body=false needs to look at the actually > messages Extending notmuch to help with this was next on my list of things to do. At the moment I just needed a solution that worked. > I should emphasise that none of the above means I am opposed to the > patch: having respectable built in address-completion support would be > very nice. Cool, thanks! ^ permalink raw reply [flat|nested] 11+ messages in thread
* [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
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).