On Thu, Oct 23 2014, Mark Walters <markwalters1009@gmail.com> wrote: > On Sun, 12 Oct 2014, Michal Sojka <sojkam1@fel.cvut.cz> wrote: >> The new outputs allow printing senders, recipients or both of matching >> messages. The --output option is converted from "keyword" argument to >> "flags" argument, which means that the user can use --output=sender and >> --output=recipients simultaneously, to print both. Other combinations >> produce an error. >> >> ... >> >> +static void >> +print_address_list (const search_options_t *o, 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 (o, 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 (o->format, "%s <%s>", name, addr); >> + else >> + full_address = talloc_strdup (o->format, addr); >> + >> + if (!full_address) { >> + fprintf (stderr, "Error: out of memory\n"); >> + break; >> + } >> + o->format->string (o->format, full_address); >> + o->format->separator (o->format); >> + >> + talloc_free (full_address); > > Thinking about this some more how about printing the name and address as > a structured pair/map (at least for all cases except text/text0 output): > something like (in JSON) > [name: "John Doe" address: "john.doe@example.com"] > > It seems wrong to me to go to the effort of separating them in the C and > then combining them in the output. > > This could also help with the questions about uniqueness. If the client > can get the data ready parsed into name/address then it can deal with > much of the uniqueness itself. In that case client can also filter based on some substring, reducing the memory requirements... > > My preference would be for the default to print one line for each > distinct full_address, and then any filter-by options to refine from > there. Hmm, now I cannot decide whether this or just print out all addresses of messages, or do this distinct full_address output -- it looks like all other --output options prints unique lines, but there is potential of quite a lot of memory usage there... ... probably the memory usage is not problem there, OOM-killer eventually does it's job if necessary (!) (but machine may be slow (and trashing) for a while (just thinking out loud)) (!) but could we have general filter option for search to drop data before it is even considered for caching! -- maybe later ? > One other advantage of structuring the output is that it is extensible: > for example, at some later stage, we could include a "count" in the map > allowing the client can pick the most popular variant. , and in this case notmuch cannot print any output until the full address list is gathered... :D > > Best wishes > > Mark Tomi > > > > >> + } >> + } >> +} >> + >> +static void >> +print_address_string (const search_options_t *o, const char *recipients) >> +{ >> + InternetAddressList *list; >> + >> + if (recipients == NULL) >> + return; >> + >> + list = internet_address_list_parse_string (recipients); >> + if (list == NULL) >> + return; >> + >> + print_address_list (o, list); >> +} >> + >> static int >> do_search_messages (search_options_t *o) >> { >> @@ -266,11 +330,29 @@ do_search_messages (search_options_t *o) >> >> notmuch_filenames_destroy( filenames ); >> >> - } else { /* output == OUTPUT_MESSAGES */ >> + } else if (o->output == OUTPUT_MESSAGES) { >> format->set_prefix (format, "id"); >> format->string (format, >> notmuch_message_get_message_id (message)); >> format->separator (format); >> + } else { >> + if (o->output & OUTPUT_SENDER) { >> + const char *addrs; >> + >> + addrs = notmuch_message_get_header (message, "from"); >> + print_address_string (o, addrs); >> + } >> + >> + if (o->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 (o, addrs); >> + } >> + } >> } >> >> notmuch_message_destroy (message); >> @@ -337,7 +419,7 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[]) >> notmuch_database_t *notmuch; >> search_options_t o = { >> .sort = NOTMUCH_SORT_NEWEST_FIRST, >> - .output = OUTPUT_SUMMARY, >> + .output = 0, >> .offset = 0, >> .limit = -1, /* unlimited */ >> .dupe = -1, >> @@ -366,10 +448,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, &o.output, "output", 'o', >> + { NOTMUCH_OPT_KEYWORD_FLAGS, &o.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 } } }, >> @@ -389,6 +473,9 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[]) >> if (opt_index < 0) >> return EXIT_FAILURE; >> >> + if (! o.output) >> + o.output = OUTPUT_SUMMARY; >> + >> switch (format_sel) { >> case NOTMUCH_FORMAT_TEXT: >> o.format = sprinter_text_create (config, stdout); >> @@ -455,18 +542,23 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[]) >> } >> >> switch (o.output) { >> - default: >> case OUTPUT_SUMMARY: >> case OUTPUT_THREADS: >> ret = do_search_threads (&o); >> break; >> case OUTPUT_MESSAGES: >> + case OUTPUT_SENDER: >> + case OUTPUT_RECIPIENTS: >> + case OUTPUT_ADDRESSES: >> case OUTPUT_FILES: >> ret = do_search_messages (&o); >> break; >> case OUTPUT_TAGS: >> ret = do_search_tags (notmuch, o.format, o.query); >> break; >> + default: >> + fprintf (stderr, "Error: the combination of outputs is not supported.\n"); >> + ret = 1; >> } >> >> notmuch_query_destroy (o.query); >> diff --git a/test/T090-search-output.sh b/test/T090-search-output.sh >> index 947d572..e696c01 100755 >> --- a/test/T090-search-output.sh >> +++ b/test/T090-search-output.sh >> @@ -387,6 +387,70 @@ cat <<EOF >EXPECTED >> EOF >> test_expect_equal_file OUTPUT EXPECTED >> >> +test_begin_subtest "--output=sender" >> +notmuch search --output=sender '*' | sort | uniq --count >OUTPUT >> +cat <<EOF >EXPECTED >> + 1 Adrian Perez de Castro <aperez@igalia.com> >> + 2 Alex Botero-Lowry <alex.boterolowry@gmail.com> >> + 4 Alexander Botero-Lowry <alex.boterolowry@gmail.com> >> + 1 Aron Griffis <agriffis@n01se.net> >> + 12 Carl Worth <cworth@cworth.org> >> + 1 Chris Wilson <chris@chris-wilson.co.uk> >> + 1 François Boulogne <boulogne.f@gmail.com> >> + 1 Ingmar Vanhassel <ingmar@exherbo.org> >> + 1 Israel Herraiz <isra@herraiz.org> >> + 4 Jan Janak <jan@ryngle.com> >> + 2 Jjgod Jiang <gzjjgod@gmail.com> >> + 7 Keith Packard <keithp@keithp.com> >> + 5 Lars Kellogg-Stedman <lars@seas.harvard.edu> >> + 5 Mikhail Gusarov <dottedmag@dottedmag.net> >> + 1 Olivier Berger <olivier.berger@it-sudparis.eu> >> + 1 Rolland Santimano <rollandsantimano@yahoo.com> >> + 3 Stewart Smith <stewart@flamingspork.com> >> +EOF >> +test_expect_equal_file OUTPUT EXPECTED >> + >> +test_begin_subtest "--output=recipients" >> +notmuch search --output=recipients '*' | sort | uniq --count >OUTPUT >> +cat <<EOF >EXPECTED >> + 1 Allan McRae <allan@archlinux.org> >> + 1 Discussion about the Arch User Repository (AUR) <aur-general@archlinux.org> >> + 1 Keith Packard <keithp@keithp.com> >> + 1 Mikhail Gusarov <dottedmag@dottedmag.net> >> + 2 notmuch <notmuch@notmuchmail.org> >> + 48 notmuch@notmuchmail.org >> + 1 olivier.berger@it-sudparis.eu >> +EOF >> +test_expect_equal_file OUTPUT EXPECTED >> + >> +test_begin_subtest "--output=sender --output=recipients" >> +notmuch search --output=sender --output=recipients '*' | sort | uniq --count >OUTPUT >> +cat <<EOF >EXPECTED >> + 1 Adrian Perez de Castro <aperez@igalia.com> >> + 2 Alex Botero-Lowry <alex.boterolowry@gmail.com> >> + 4 Alexander Botero-Lowry <alex.boterolowry@gmail.com> >> + 1 Allan McRae <allan@archlinux.org> >> + 1 Aron Griffis <agriffis@n01se.net> >> + 12 Carl Worth <cworth@cworth.org> >> + 1 Chris Wilson <chris@chris-wilson.co.uk> >> + 1 Discussion about the Arch User Repository (AUR) <aur-general@archlinux.org> >> + 1 François Boulogne <boulogne.f@gmail.com> >> + 1 Ingmar Vanhassel <ingmar@exherbo.org> >> + 1 Israel Herraiz <isra@herraiz.org> >> + 4 Jan Janak <jan@ryngle.com> >> + 2 Jjgod Jiang <gzjjgod@gmail.com> >> + 8 Keith Packard <keithp@keithp.com> >> + 5 Lars Kellogg-Stedman <lars@seas.harvard.edu> >> + 6 Mikhail Gusarov <dottedmag@dottedmag.net> >> + 1 Olivier Berger <olivier.berger@it-sudparis.eu> >> + 1 Rolland Santimano <rollandsantimano@yahoo.com> >> + 3 Stewart Smith <stewart@flamingspork.com> >> + 2 notmuch <notmuch@notmuchmail.org> >> + 48 notmuch@notmuchmail.org >> + 1 olivier.berger@it-sudparis.eu >> +EOF >> +test_expect_equal_file OUTPUT EXPECTED >> + >> test_begin_subtest "sanitize output for quoted-printable line-breaks in author and subject" >> add_message "[subject]='two =?ISO-8859-1?Q?line=0A_subject?= >> headers'" >> -- >> 2.1.1 >> >> _______________________________________________ >> notmuch mailing list >> notmuch@notmuchmail.org >> http://notmuchmail.org/mailman/listinfo/notmuch > _______________________________________________ > notmuch mailing list > notmuch@notmuchmail.org > http://notmuchmail.org/mailman/listinfo/notmuch