[PATCH v6 6/7] cli: search: Add --output=count

2014-11-03 Thread Michal Sojka
Hi Tomi,

On Mon, Nov 03 2014, Tomi Ollila wrote:
> On Sun, Nov 02 2014, Michal Sojka  wrote:
>
>> On 2. listopadu 2014 10:29:28 CET, Mark Walters > gmail.com> wrote:
>>>
>>>Hi
>>>
>>>On Sun, 02 Nov 2014, Michal Sojka  wrote:
 On Sat, Nov 01 2014, Mark Walters wrote:
> On Fri, 31 Oct 2014, Michal Sojka  wrote:
>> This output can be used with --output=recipients or --output=sender
>> and in addition to the addresses, it prints how many times was each
>> address encountered during search.
>
> Hi
>
> I have a couple comments on this patch.
>
>> ---
>>  completion/notmuch-completion.bash |  2 +-
>>  completion/notmuch-completion.zsh  |  2 +-
>>  doc/man1/notmuch-search.rst|  9 +--
>>  notmuch-search.c   | 51
>>>--
>>  4 files changed, 52 insertions(+), 12 deletions(-)
>>
>> diff --git a/completion/notmuch-completion.bash
>>>b/completion/notmuch-completion.bash
>> index cfbd389..39cd829 100644
>> --- a/completion/notmuch-completion.bash
>> +++ b/completion/notmuch-completion.bash
>> @@ -294,7 +294,7 @@ _notmuch_search()
>>  return
>>  ;;
>>  --output)
>> -COMPREPLY=( $( compgen -W "summary threads messages files
>>>tags sender recipients" -- "${cur}" ) )
>> +COMPREPLY=( $( compgen -W "summary threads messages files
>>>tags sender recipients count" -- "${cur}" ) )
>>  return
>>  ;;
>>  --sort)
>> diff --git a/completion/notmuch-completion.zsh
>>>b/completion/notmuch-completion.zsh
>> index 3e52a00..d7e5a5e 100644
>> --- a/completion/notmuch-completion.zsh
>> +++ b/completion/notmuch-completion.zsh
>> @@ -53,7 +53,7 @@ _notmuch_search()
>>  '--max-threads=[display only the first x threads from the
>>>search results]:number of threads to show: ' \
>>  '--first=[omit the first x threads from the search
>>>results]:number of threads to omit: ' \
>>  '--sort=[sort results]:sorting:((newest-first\:"reverse
>>>chronological order" oldest-first\:"chronological order"))' \
>> -'--output=[select what to output]:output:((summary threads
>>>messages files tags sender recipients))'
>> +'--output=[select what to output]:output:((summary threads
>>>messages files tags sender recipients count))'
>>  }
>>  
>>  _notmuch()
>> diff --git a/doc/man1/notmuch-search.rst
>>>b/doc/man1/notmuch-search.rst
>> index 42f17e4..ec89200 100644
>> --- a/doc/man1/notmuch-search.rst
>> +++ b/doc/man1/notmuch-search.rst
>> @@ -96,9 +96,14 @@ Supported options for **search** include
>>  Like **sender** but for addresses from *To*, *Cc* and
>>  *Bcc* headers.
>>  
>> +**count**
>> +Can be used in combination with **sender** or
>> +**recipients** to print the count of how many times was
>> +the address encountered during search.
>> +
>>  This option can be given multiple times to combine different
>> -outputs. Currently, this is only supported for **sender** and
>> -**recipients** outputs.
>> +outputs. Currently, this is only supported for **sender**,
>> +**recipients** and **count** outputs.
>
> It might be worth saying that the results will be slower if count is
> specified.

 I wrote something like this in
 id:1414889400-30977-10-git-send-email-sojkam1 at fel.cvut.cz.

>
>>  ``--sort=``\ (**newest-first**\ \|\ **oldest-first**)
>
> I think sort works as expected if count is not specified, but does
>>>not
> with count. 

 Agreed.

> Maybe count can be done by doing two passes? 

 What do you mean by pass?
>>>
>>>I mean iterating through the messages twice: so the first time would
>>>fill in the count in the hash map, and the second iteration would print
>>>the addresses.
>>
>> That's what the patch does. Only the second time it iterates the hash.
>
> Sorry 
>
> And we loose the order ? (or not ?) do we have "orderedhash" there...
> I'd like to save the order

What would be the use case?

If you really want to preserve the order, we could save a sequence
number in mailbox_t and sort the hash table entries before printing. But
this could be implemented later and enabled by a special command line
option. notmuch search --output=tags does not preserve order either.

> (but that is not so important) -- but more importantly, are tests
> robusts --- ah there is sort -n in the test...

Yes.

-Michal


[DRAFT PATCH] modified notmuch-emacs-mua

2014-11-03 Thread Jameson Graef Rollins
On Thu, Jul 10 2014, Tomi Ollila  wrote:
> Highlights:
>
> * notmuch-emacs-mua without arguments runs (notmuch-hello)
>
> * runs emacs(1) in case emacsclient(1) fails to connect to running emacs
>
> * takes -nw option
>
> * handles mailto:
>
> * --from option when sending non-mailto: way
>
> * -i includes file --body[= ]string inserts string

Hi, Tomi.  I think including an emacs CLI like this is probably a good
idea.  I might not use it myself, since I've already concocted one for
my personal use, but I still think it's a good idea.

The particular thing I'm interested in, though, is mailto: URL handling:

> + mailto:*)
> + oIFS=$IFS; IFS=; OPTARG="$*" IFS=$oIFS
> + escape_optarg
> + exec_mua "(progn (require 'notmuch) (browse-url-mail \"$OPTARG\"))"
> + exit
> +esac

I have submitted multiple revisions of a patch that handles mailto: URLs
in notmuch-mua.el:

id:1334438868-17168-1-git-send-email-jrollins at finestructure.net

It hasn't been accepted yet, though.  I've tried browse-url-mail before,
and it would be convenient to use it.  However, used on it's own it has
the problem that it doesn't open new message buffer in the "notmuch"
way.  For instance, I prefer my new notmuch buffers to appear in new
frames.  browse-url-mail doesn't respect this.  Maybe it could be
wrapped in a notmuch-mua-mailto function, or you could instead be using
the function I submitted?

I've been a bit out of touch for a while, so forgive me if anything has
change that I'm not aware of.

jamie.
-- next part --
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 818 bytes
Desc: not available
URL: 
<http://notmuchmail.org/pipermail/notmuch/attachments/20141103/7fe29127/attachment.pgp>


[PATCH v6 6/7] cli: search: Add --output=count

2014-11-03 Thread Tomi Ollila
On Sun, Nov 02 2014, Michal Sojka  wrote:

> On 2. listopadu 2014 10:29:28 CET, Mark Walters  gmail.com> wrote:
>>
>>Hi
>>
>>On Sun, 02 Nov 2014, Michal Sojka  wrote:
>>> On Sat, Nov 01 2014, Mark Walters wrote:
 On Fri, 31 Oct 2014, Michal Sojka  wrote:
> This output can be used with --output=recipients or --output=sender
> and in addition to the addresses, it prints how many times was each
> address encountered during search.

 Hi

 I have a couple comments on this patch.

> ---
>  completion/notmuch-completion.bash |  2 +-
>  completion/notmuch-completion.zsh  |  2 +-
>  doc/man1/notmuch-search.rst|  9 +--
>  notmuch-search.c   | 51
>>--
>  4 files changed, 52 insertions(+), 12 deletions(-)
>
> diff --git a/completion/notmuch-completion.bash
>>b/completion/notmuch-completion.bash
> index cfbd389..39cd829 100644
> --- a/completion/notmuch-completion.bash
> +++ b/completion/notmuch-completion.bash
> @@ -294,7 +294,7 @@ _notmuch_search()
>   return
>   ;;
>   --output)
> - COMPREPLY=( $( compgen -W "summary threads messages files
>>tags sender recipients" -- "${cur}" ) )
> + COMPREPLY=( $( compgen -W "summary threads messages files
>>tags sender recipients count" -- "${cur}" ) )
>   return
>   ;;
>   --sort)
> diff --git a/completion/notmuch-completion.zsh
>>b/completion/notmuch-completion.zsh
> index 3e52a00..d7e5a5e 100644
> --- a/completion/notmuch-completion.zsh
> +++ b/completion/notmuch-completion.zsh
> @@ -53,7 +53,7 @@ _notmuch_search()
>  '--max-threads=[display only the first x threads from the
>>search results]:number of threads to show: ' \
>  '--first=[omit the first x threads from the search
>>results]:number of threads to omit: ' \
>  '--sort=[sort results]:sorting:((newest-first\:"reverse
>>chronological order" oldest-first\:"chronological order"))' \
> -'--output=[select what to output]:output:((summary threads
>>messages files tags sender recipients))'
> +'--output=[select what to output]:output:((summary threads
>>messages files tags sender recipients count))'
>  }
>  
>  _notmuch()
> diff --git a/doc/man1/notmuch-search.rst
>>b/doc/man1/notmuch-search.rst
> index 42f17e4..ec89200 100644
> --- a/doc/man1/notmuch-search.rst
> +++ b/doc/man1/notmuch-search.rst
> @@ -96,9 +96,14 @@ Supported options for **search** include
>  Like **sender** but for addresses from *To*, *Cc* and
>   *Bcc* headers.
>  
> + **count**
> + Can be used in combination with **sender** or
> + **recipients** to print the count of how many times was
> + the address encountered during search.
> +
>   This option can be given multiple times to combine different
> - outputs. Currently, this is only supported for **sender** and
> - **recipients** outputs.
> + outputs. Currently, this is only supported for **sender**,
> + **recipients** and **count** outputs.

 It might be worth saying that the results will be slower if count is
 specified.
>>>
>>> I wrote something like this in
>>> id:1414889400-30977-10-git-send-email-sojkam1 at fel.cvut.cz.
>>>

>  ``--sort=``\ (**newest-first**\ \|\ **oldest-first**)

 I think sort works as expected if count is not specified, but does
>>not
 with count. 
>>>
>>> Agreed.
>>>
 Maybe count can be done by doing two passes? 
>>>
>>> What do you mean by pass?
>>
>>I mean iterating through the messages twice: so the first time would
>>fill in the count in the hash map, and the second iteration would print
>>the addresses.
>
> That's what the patch does. Only the second time it iterates the hash.

Sorry 

And we loose the order ? (or not ?) do we have "orderedhash" there...
I'd like to save the order (but that is not so important) -- but
more importantly, are tests robusts --- ah there is sort -n in the test...

>
> Michal

Tomi

>
> -- 
> Odesl?no z m?ho telefonu pomoc? Kaiten Mail. Omluvte pros?m mou stru?nost.
> ___
> notmuch mailing list
> notmuch at notmuchmail.org
> http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH v6 6/7] cli: search: Add --output=count

2014-11-03 Thread Tomi Ollila
On Sun, Nov 02 2014, Michal Sojka sojk...@fel.cvut.cz wrote:

 On 2. listopadu 2014 10:29:28 CET, Mark Walters markwalters1...@gmail.com 
 wrote:

Hi

On Sun, 02 Nov 2014, Michal Sojka sojk...@fel.cvut.cz wrote:
 On Sat, Nov 01 2014, Mark Walters wrote:
 On Fri, 31 Oct 2014, Michal Sojka sojk...@fel.cvut.cz wrote:
 This output can be used with --output=recipients or --output=sender
 and in addition to the addresses, it prints how many times was each
 address encountered during search.

 Hi

 I have a couple comments on this patch.

 ---
  completion/notmuch-completion.bash |  2 +-
  completion/notmuch-completion.zsh  |  2 +-
  doc/man1/notmuch-search.rst|  9 +--
  notmuch-search.c   | 51
--
  4 files changed, 52 insertions(+), 12 deletions(-)

 diff --git a/completion/notmuch-completion.bash
b/completion/notmuch-completion.bash
 index cfbd389..39cd829 100644
 --- a/completion/notmuch-completion.bash
 +++ b/completion/notmuch-completion.bash
 @@ -294,7 +294,7 @@ _notmuch_search()
   return
   ;;
   --output)
 - COMPREPLY=( $( compgen -W summary threads messages files
tags sender recipients -- ${cur} ) )
 + COMPREPLY=( $( compgen -W summary threads messages files
tags sender recipients count -- ${cur} ) )
   return
   ;;
   --sort)
 diff --git a/completion/notmuch-completion.zsh
b/completion/notmuch-completion.zsh
 index 3e52a00..d7e5a5e 100644
 --- a/completion/notmuch-completion.zsh
 +++ b/completion/notmuch-completion.zsh
 @@ -53,7 +53,7 @@ _notmuch_search()
  '--max-threads=[display only the first x threads from the
search results]:number of threads to show: ' \
  '--first=[omit the first x threads from the search
results]:number of threads to omit: ' \
  '--sort=[sort results]:sorting:((newest-first\:reverse
chronological order oldest-first\:chronological order))' \
 -'--output=[select what to output]:output:((summary threads
messages files tags sender recipients))'
 +'--output=[select what to output]:output:((summary threads
messages files tags sender recipients count))'
  }
  
  _notmuch()
 diff --git a/doc/man1/notmuch-search.rst
b/doc/man1/notmuch-search.rst
 index 42f17e4..ec89200 100644
 --- a/doc/man1/notmuch-search.rst
 +++ b/doc/man1/notmuch-search.rst
 @@ -96,9 +96,14 @@ Supported options for **search** include
  Like **sender** but for addresses from *To*, *Cc* and
   *Bcc* headers.
  
 + **count**
 + Can be used in combination with **sender** or
 + **recipients** to print the count of how many times was
 + the address encountered during search.
 +
   This option can be given multiple times to combine different
 - outputs. Currently, this is only supported for **sender** and
 - **recipients** outputs.
 + outputs. Currently, this is only supported for **sender**,
 + **recipients** and **count** outputs.

 It might be worth saying that the results will be slower if count is
 specified.

 I wrote something like this in
 id:1414889400-30977-10-git-send-email-sojk...@fel.cvut.cz.


  ``--sort=``\ (**newest-first**\ \|\ **oldest-first**)

 I think sort works as expected if count is not specified, but does
not
 with count. 

 Agreed.

 Maybe count can be done by doing two passes? 

 What do you mean by pass?

I mean iterating through the messages twice: so the first time would
fill in the count in the hash map, and the second iteration would print
the addresses.

 That's what the patch does. Only the second time it iterates the hash.

Sorry 

And we loose the order ? (or not ?) do we have orderedhash there...
I'd like to save the order (but that is not so important) -- but
more importantly, are tests robusts --- ah there is sort -n in the test...


 Michal

Tomi


 -- 
 Odesláno z mého telefonu pomocí Kaiten Mail. Omluvte prosím mou stručnost.
 ___
 notmuch mailing list
 notmuch@notmuchmail.org
 http://notmuchmail.org/mailman/listinfo/notmuch
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [DRAFT PATCH] modified notmuch-emacs-mua

2014-11-03 Thread Jameson Graef Rollins
On Thu, Jul 10 2014, Tomi Ollila tomi.oll...@iki.fi wrote:
 Highlights:

 * notmuch-emacs-mua without arguments runs (notmuch-hello)

 * runs emacs(1) in case emacsclient(1) fails to connect to running emacs

 * takes -nw option

 * handles mailto:

 * --from option when sending non-mailto: way

 * -i includes file --body[= ]string inserts string

Hi, Tomi.  I think including an emacs CLI like this is probably a good
idea.  I might not use it myself, since I've already concocted one for
my personal use, but I still think it's a good idea.

The particular thing I'm interested in, though, is mailto: URL handling:

 + mailto:*)
 + oIFS=$IFS; IFS=; OPTARG=$* IFS=$oIFS
 + escape_optarg
 + exec_mua (progn (require 'notmuch) (browse-url-mail \$OPTARG\))
 + exit
 +esac

I have submitted multiple revisions of a patch that handles mailto: URLs
in notmuch-mua.el:

id:1334438868-17168-1-git-send-email-jroll...@finestructure.net

It hasn't been accepted yet, though.  I've tried browse-url-mail before,
and it would be convenient to use it.  However, used on it's own it has
the problem that it doesn't open new message buffer in the notmuch
way.  For instance, I prefer my new notmuch buffers to appear in new
frames.  browse-url-mail doesn't respect this.  Maybe it could be
wrapped in a notmuch-mua-mailto function, or you could instead be using
the function I submitted?

I've been a bit out of touch for a while, so forgive me if anything has
change that I'm not aware of.

jamie.


pgp9NjsOJTGDl.pgp
Description: PGP signature
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH v6 6/7] cli: search: Add --output=count

2014-11-03 Thread Michal Sojka
Hi Tomi,

On Mon, Nov 03 2014, Tomi Ollila wrote:
 On Sun, Nov 02 2014, Michal Sojka sojk...@fel.cvut.cz wrote:

 On 2. listopadu 2014 10:29:28 CET, Mark Walters markwalters1...@gmail.com 
 wrote:

Hi

On Sun, 02 Nov 2014, Michal Sojka sojk...@fel.cvut.cz wrote:
 On Sat, Nov 01 2014, Mark Walters wrote:
 On Fri, 31 Oct 2014, Michal Sojka sojk...@fel.cvut.cz wrote:
 This output can be used with --output=recipients or --output=sender
 and in addition to the addresses, it prints how many times was each
 address encountered during search.

 Hi

 I have a couple comments on this patch.

 ---
  completion/notmuch-completion.bash |  2 +-
  completion/notmuch-completion.zsh  |  2 +-
  doc/man1/notmuch-search.rst|  9 +--
  notmuch-search.c   | 51
--
  4 files changed, 52 insertions(+), 12 deletions(-)

 diff --git a/completion/notmuch-completion.bash
b/completion/notmuch-completion.bash
 index cfbd389..39cd829 100644
 --- a/completion/notmuch-completion.bash
 +++ b/completion/notmuch-completion.bash
 @@ -294,7 +294,7 @@ _notmuch_search()
  return
  ;;
  --output)
 -COMPREPLY=( $( compgen -W summary threads messages files
tags sender recipients -- ${cur} ) )
 +COMPREPLY=( $( compgen -W summary threads messages files
tags sender recipients count -- ${cur} ) )
  return
  ;;
  --sort)
 diff --git a/completion/notmuch-completion.zsh
b/completion/notmuch-completion.zsh
 index 3e52a00..d7e5a5e 100644
 --- a/completion/notmuch-completion.zsh
 +++ b/completion/notmuch-completion.zsh
 @@ -53,7 +53,7 @@ _notmuch_search()
  '--max-threads=[display only the first x threads from the
search results]:number of threads to show: ' \
  '--first=[omit the first x threads from the search
results]:number of threads to omit: ' \
  '--sort=[sort results]:sorting:((newest-first\:reverse
chronological order oldest-first\:chronological order))' \
 -'--output=[select what to output]:output:((summary threads
messages files tags sender recipients))'
 +'--output=[select what to output]:output:((summary threads
messages files tags sender recipients count))'
  }
  
  _notmuch()
 diff --git a/doc/man1/notmuch-search.rst
b/doc/man1/notmuch-search.rst
 index 42f17e4..ec89200 100644
 --- a/doc/man1/notmuch-search.rst
 +++ b/doc/man1/notmuch-search.rst
 @@ -96,9 +96,14 @@ Supported options for **search** include
  Like **sender** but for addresses from *To*, *Cc* and
  *Bcc* headers.
  
 +**count**
 +Can be used in combination with **sender** or
 +**recipients** to print the count of how many times was
 +the address encountered during search.
 +
  This option can be given multiple times to combine different
 -outputs. Currently, this is only supported for **sender** and
 -**recipients** outputs.
 +outputs. Currently, this is only supported for **sender**,
 +**recipients** and **count** outputs.

 It might be worth saying that the results will be slower if count is
 specified.

 I wrote something like this in
 id:1414889400-30977-10-git-send-email-sojk...@fel.cvut.cz.


  ``--sort=``\ (**newest-first**\ \|\ **oldest-first**)

 I think sort works as expected if count is not specified, but does
not
 with count. 

 Agreed.

 Maybe count can be done by doing two passes? 

 What do you mean by pass?

I mean iterating through the messages twice: so the first time would
fill in the count in the hash map, and the second iteration would print
the addresses.

 That's what the patch does. Only the second time it iterates the hash.

 Sorry 

 And we loose the order ? (or not ?) do we have orderedhash there...
 I'd like to save the order

What would be the use case?

If you really want to preserve the order, we could save a sequence
number in mailbox_t and sort the hash table entries before printing. But
this could be implemented later and enabled by a special command line
option. notmuch search --output=tags does not preserve order either.

 (but that is not so important) -- but more importantly, are tests
 robusts --- ah there is sort -n in the test...

Yes.

-Michal
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v2 02/10] cli: search: Move more variables into search_context_t

2014-11-03 Thread Michal Sojka
Just refactoring, no functional changes.
---
 notmuch-search.c | 49 ++---
 1 file changed, 26 insertions(+), 23 deletions(-)

diff --git a/notmuch-search.c b/notmuch-search.c
index 2c47b80..3d2012b 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -34,8 +34,18 @@ typedef enum {
 
 #define OUTPUT_ADDRESS_FLAGS (OUTPUT_SENDER | OUTPUT_RECIPIENTS)
 
+typedef enum {
+NOTMUCH_FORMAT_JSON,
+NOTMUCH_FORMAT_TEXT,
+NOTMUCH_FORMAT_TEXT0,
+NOTMUCH_FORMAT_SEXP
+} format_sel_t;
+
 typedef struct {
+notmuch_database_t *notmuch;
+format_sel_t format_sel;
 sprinter_t *format;
+notmuch_exclude_t exclude;
 notmuch_query_t *query;
 notmuch_sort_t sort;
 output_t output;
@@ -413,14 +423,14 @@ do_search_messages (search_context_t *ctx)
 }
 
 static int
-do_search_tags (notmuch_database_t *notmuch,
-   const search_context_t *ctx)
+do_search_tags (const search_context_t *ctx)
 {
 notmuch_messages_t *messages = NULL;
 notmuch_tags_t *tags;
 const char *tag;
 sprinter_t *format = ctx-format;
 notmuch_query_t *query = ctx-query;
+notmuch_database_t *notmuch = ctx-notmuch;
 
 /* should the following only special case if no excluded terms
  * specified? */
@@ -464,8 +474,9 @@ do_search_tags (notmuch_database_t *notmuch,
 int
 notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
 {
-notmuch_database_t *notmuch;
 search_context_t ctx = {
+   .format_sel = NOTMUCH_FORMAT_TEXT,
+   .exclude = NOTMUCH_EXCLUDE_TRUE,
.sort = NOTMUCH_SORT_NEWEST_FIRST,
.output = 0,
.offset = 0,
@@ -474,22 +485,14 @@ notmuch_search_command (notmuch_config_t *config, int 
argc, char *argv[])
 };
 char *query_str;
 int opt_index, ret;
-notmuch_exclude_t exclude = NOTMUCH_EXCLUDE_TRUE;
 unsigned int i;
 
-enum {
-   NOTMUCH_FORMAT_JSON,
-   NOTMUCH_FORMAT_TEXT,
-   NOTMUCH_FORMAT_TEXT0,
-   NOTMUCH_FORMAT_SEXP
-} format_sel = NOTMUCH_FORMAT_TEXT;
-
 notmuch_opt_desc_t options[] = {
{ NOTMUCH_OPT_KEYWORD, ctx.sort, sort, 's',
  (notmuch_keyword_t []){ { oldest-first, NOTMUCH_SORT_OLDEST_FIRST },
  { newest-first, NOTMUCH_SORT_NEWEST_FIRST },
  { 0, 0 } } },
-   { NOTMUCH_OPT_KEYWORD, format_sel, format, 'f',
+   { NOTMUCH_OPT_KEYWORD, ctx.format_sel, format, 'f',
  (notmuch_keyword_t []){ { json, NOTMUCH_FORMAT_JSON },
  { sexp, NOTMUCH_FORMAT_SEXP },
  { text, NOTMUCH_FORMAT_TEXT },
@@ -505,7 +508,7 @@ notmuch_search_command (notmuch_config_t *config, int argc, 
char *argv[])
  { files, OUTPUT_FILES },
  { tags, OUTPUT_TAGS },
  { 0, 0 } } },
-{ NOTMUCH_OPT_KEYWORD, exclude, exclude, 'x',
+{ NOTMUCH_OPT_KEYWORD, ctx.exclude, exclude, 'x',
   (notmuch_keyword_t []){ { true, NOTMUCH_EXCLUDE_TRUE },
   { false, NOTMUCH_EXCLUDE_FALSE },
   { flag, NOTMUCH_EXCLUDE_FLAG },
@@ -530,7 +533,7 @@ notmuch_search_command (notmuch_config_t *config, int argc, 
char *argv[])
 return EXIT_FAILURE;
 }
 
-switch (format_sel) {
+switch (ctx.format_sel) {
 case NOTMUCH_FORMAT_TEXT:
ctx.format = sprinter_text_create (config, stdout);
break;
@@ -555,10 +558,10 @@ notmuch_search_command (notmuch_config_t *config, int 
argc, char *argv[])
 notmuch_exit_if_unsupported_format ();
 
 if (notmuch_database_open (notmuch_config_get_database_path (config),
-  NOTMUCH_DATABASE_MODE_READ_ONLY, notmuch))
+  NOTMUCH_DATABASE_MODE_READ_ONLY, ctx.notmuch))
return EXIT_FAILURE;
 
-query_str = query_string_from_args (notmuch, argc-opt_index, 
argv+opt_index);
+query_str = query_string_from_args (ctx.notmuch, argc-opt_index, 
argv+opt_index);
 if (query_str == NULL) {
fprintf (stderr, Out of memory.\n);
return EXIT_FAILURE;
@@ -568,7 +571,7 @@ notmuch_search_command (notmuch_config_t *config, int argc, 
char *argv[])
return EXIT_FAILURE;
 }
 
-ctx.query = notmuch_query_create (notmuch, query_str);
+ctx.query = notmuch_query_create (ctx.notmuch, query_str);
 if (ctx.query == NULL) {
fprintf (stderr, Out of memory\n);
return EXIT_FAILURE;
@@ -576,15 +579,15 @@ notmuch_search_command (notmuch_config_t *config, int 
argc, char *argv[])
 
 notmuch_query_set_sort (ctx.query, ctx.sort);
 
-if (exclude == NOTMUCH_EXCLUDE_FLAG  ctx.output != OUTPUT_SUMMARY) {
+if (ctx.exclude == NOTMUCH_EXCLUDE_FLAG  ctx.output != OUTPUT_SUMMARY) {
/* If we are not doing summary output there is nowhere to
 * print the excluded flag so fall 

[PATCH v2 06/10] cli: Introduce notmuch address command

2014-11-03 Thread Michal Sojka
This moves address-related functionality from search command to the
new address command. The implementation shares almost all code and
some command line options.

Options --offset and --limit were intentionally not included in the
address command, because they refer to messages numbers, which users
do not see in the output. This could confuse users because, for
example, they could see more addresses in the output that what was
specified with --limit. This functionality can be correctly
reimplemented for addresses later.

This was inspired by a patch from Jani Nikula.
---
 completion/notmuch-completion.bash |  42 ++-
 completion/notmuch-completion.zsh  |  10 +++-
 doc/man1/notmuch-address.rst   |  99 
 doc/man1/notmuch-search.rst|  20 +---
 doc/man1/notmuch.rst   |   7 +--
 notmuch-client.h   |   3 ++
 notmuch-search.c   | 101 +
 notmuch.c  |   2 +
 8 files changed, 228 insertions(+), 56 deletions(-)
 create mode 100644 doc/man1/notmuch-address.rst

diff --git a/completion/notmuch-completion.bash 
b/completion/notmuch-completion.bash
index cfbd389..94ea2d5 100644
--- a/completion/notmuch-completion.bash
+++ b/completion/notmuch-completion.bash
@@ -294,7 +294,7 @@ _notmuch_search()
return
;;
--output)
-   COMPREPLY=( $( compgen -W summary threads messages files tags 
sender recipients -- ${cur} ) )
+   COMPREPLY=( $( compgen -W summary threads messages files tags -- 
${cur} ) )
return
;;
--sort)
@@ -320,6 +320,44 @@ _notmuch_search()
 esac
 }
 
+_notmuch_address()
+{
+local cur prev words cword split
+_init_completion -s || return
+
+$split 
+case ${prev} in
+   --format)
+   COMPREPLY=( $( compgen -W json sexp text text0 -- ${cur} ) )
+   return
+   ;;
+   --output)
+   COMPREPLY=( $( compgen -W sender recipients -- ${cur} ) )
+   return
+   ;;
+   --sort)
+   COMPREPLY=( $( compgen -W newest-first oldest-first -- ${cur} ) 
)
+   return
+   ;;
+   --exclude)
+   COMPREPLY=( $( compgen -W true false flag all -- ${cur} ) )
+   return
+   ;;
+esac
+
+! $split 
+case ${cur} in
+   -*)
+   local options=--format= --output= --sort= --exclude=
+   compopt -o nospace
+   COMPREPLY=( $(compgen -W $options -- ${cur}) )
+   ;;
+   *)
+   _notmuch_search_terms
+   ;;
+esac
+}
+
 _notmuch_show()
 {
 local cur prev words cword split
@@ -393,7 +431,7 @@ _notmuch_tag()
 
 _notmuch()
 {
-local _notmuch_commands=compact config count dump help insert new reply 
restore search setup show tag
+local _notmuch_commands=compact config count dump help insert new reply 
restore search address setup show tag
 local arg cur prev words cword split
 
 # require bash-completion with _init_completion
diff --git a/completion/notmuch-completion.zsh 
b/completion/notmuch-completion.zsh
index 3e52a00..c606b75 100644
--- a/completion/notmuch-completion.zsh
+++ b/completion/notmuch-completion.zsh
@@ -10,6 +10,7 @@ _notmuch_commands()
 'setup:interactively set up notmuch for first use'
 'new:find and import any new message to the database'
 'search:search for messages matching the search terms, display matching 
threads as results'
+'address:get addresses from messages matching the given search terms'
 'reply:constructs a reply template for a set of messages'
 'show:show all messages matching the search terms'
 'tag:add or remove tags for all messages matching the search terms'
@@ -53,7 +54,14 @@ _notmuch_search()
 '--max-threads=[display only the first x threads from the search 
results]:number of threads to show: ' \
 '--first=[omit the first x threads from the search results]:number of 
threads to omit: ' \
 '--sort=[sort results]:sorting:((newest-first\:reverse chronological 
order oldest-first\:chronological order))' \
-'--output=[select what to output]:output:((summary threads messages files 
tags sender recipients))'
+'--output=[select what to output]:output:((summary threads messages files 
tags))'
+}
+
+_notmuch_address()
+{
+  _arguments -s : \
+'--sort=[sort results]:sorting:((newest-first\:reverse chronological 
order oldest-first\:chronological order))' \
+'--output=[select what to output]:output:((sender recipients))'
 }
 
 _notmuch()
diff --git a/doc/man1/notmuch-address.rst b/doc/man1/notmuch-address.rst
new file mode 100644
index 000..8109f11
--- /dev/null
+++ b/doc/man1/notmuch-address.rst
@@ -0,0 +1,99 @@
+===
+notmuch-address
+===
+
+SYNOPSIS
+
+
+**notmuch** **address** [*option* ...] *search-term* ...
+
+DESCRIPTION
+===
+
+Search for messages matching the given 

[PATCH v2 04/10] cli: search: Split notmuch_search_command to smaller functions

2014-11-03 Thread Michal Sojka
In the next commit, these functions will be used to share some
functionality between search and address commands.
---
 notmuch-search.c | 155 ++-
 1 file changed, 86 insertions(+), 69 deletions(-)

diff --git a/notmuch-search.c b/notmuch-search.c
index 6765a16..f115359 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -471,6 +471,89 @@ do_search_tags (const search_context_t *ctx)
 return 0;
 }
 
+static int
+_notmuch_search_prepare (search_context_t *ctx, notmuch_config_t *config, int 
argc, char *argv[])
+{
+char *query_str;
+unsigned int i;
+
+switch (ctx-format_sel) {
+case NOTMUCH_FORMAT_TEXT:
+   ctx-format = sprinter_text_create (config, stdout);
+   break;
+case NOTMUCH_FORMAT_TEXT0:
+   if (ctx-output == OUTPUT_SUMMARY) {
+   fprintf (stderr, Error: --format=text0 is not compatible with 
--output=summary.\n);
+   return EXIT_FAILURE;
+   }
+   ctx-format = sprinter_text0_create (config, stdout);
+   break;
+case NOTMUCH_FORMAT_JSON:
+   ctx-format = sprinter_json_create (config, stdout);
+   break;
+case NOTMUCH_FORMAT_SEXP:
+   ctx-format = sprinter_sexp_create (config, stdout);
+   break;
+default:
+   /* this should never happen */
+   INTERNAL_ERROR(no output format selected);
+}
+
+notmuch_exit_if_unsupported_format ();
+
+if (notmuch_database_open (notmuch_config_get_database_path (config),
+  NOTMUCH_DATABASE_MODE_READ_ONLY, ctx-notmuch))
+   return EXIT_FAILURE;
+
+query_str = query_string_from_args (ctx-notmuch, argc, argv);
+if (query_str == NULL) {
+   fprintf (stderr, Out of memory.\n);
+   return EXIT_FAILURE;
+}
+if (*query_str == '\0') {
+   fprintf (stderr, Error: notmuch search requires at least one search 
term.\n);
+   return EXIT_FAILURE;
+}
+
+ctx-query = notmuch_query_create (ctx-notmuch, query_str);
+if (ctx-query == NULL) {
+   fprintf (stderr, Out of memory\n);
+   return EXIT_FAILURE;
+}
+
+notmuch_query_set_sort (ctx-query, ctx-sort);
+
+if (ctx-exclude == NOTMUCH_EXCLUDE_FLAG  ctx-output != OUTPUT_SUMMARY) 
{
+   /* If we are not doing summary output there is nowhere to
+* print the excluded flag so fall back on including the
+* excluded messages. */
+   fprintf (stderr, Warning: this output format cannot flag excluded 
messages.\n);
+   ctx-exclude = NOTMUCH_EXCLUDE_FALSE;
+}
+
+if (ctx-exclude != NOTMUCH_EXCLUDE_FALSE) {
+   const char **search_exclude_tags;
+   size_t search_exclude_tags_length;
+
+   search_exclude_tags = notmuch_config_get_search_exclude_tags
+   (config, search_exclude_tags_length);
+   for (i = 0; i  search_exclude_tags_length; i++)
+   notmuch_query_add_tag_exclude (ctx-query, search_exclude_tags[i]);
+   notmuch_query_set_omit_excluded (ctx-query, ctx-exclude);
+}
+
+return 0;
+}
+
+static void
+_notmuch_search_cleanup (search_context_t *ctx)
+{
+notmuch_query_destroy (ctx-query);
+notmuch_database_destroy (ctx-notmuch);
+
+talloc_free (ctx-format);
+}
+
 int
 notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
 {
@@ -484,9 +567,7 @@ notmuch_search_command (notmuch_config_t *config, int argc, 
char *argv[])
.dupe = -1,
 };
 search_context_t *ctx = search_context;
-char *query_str;
 int opt_index, ret;
-unsigned int i;
 
 notmuch_opt_desc_t options[] = {
{ NOTMUCH_OPT_KEYWORD, ctx-sort, sort, 's',
@@ -534,71 +615,10 @@ notmuch_search_command (notmuch_config_t *config, int 
argc, char *argv[])
 return EXIT_FAILURE;
 }
 
-switch (ctx-format_sel) {
-case NOTMUCH_FORMAT_TEXT:
-   ctx-format = sprinter_text_create (config, stdout);
-   break;
-case NOTMUCH_FORMAT_TEXT0:
-   if (ctx-output == OUTPUT_SUMMARY) {
-   fprintf (stderr, Error: --format=text0 is not compatible with 
--output=summary.\n);
-   return EXIT_FAILURE;
-   }
-   ctx-format = sprinter_text0_create (config, stdout);
-   break;
-case NOTMUCH_FORMAT_JSON:
-   ctx-format = sprinter_json_create (config, stdout);
-   break;
-case NOTMUCH_FORMAT_SEXP:
-   ctx-format = sprinter_sexp_create (config, stdout);
-   break;
-default:
-   /* this should never happen */
-   INTERNAL_ERROR(no output format selected);
-}
-
-notmuch_exit_if_unsupported_format ();
-
-if (notmuch_database_open (notmuch_config_get_database_path (config),
-  NOTMUCH_DATABASE_MODE_READ_ONLY, ctx-notmuch))
+if (_notmuch_search_prepare (ctx, config,
+argc - opt_index, argv + opt_index))
return EXIT_FAILURE;
 
-query_str = query_string_from_args (ctx-notmuch, argc-opt_index, 
argv+opt_index);
-if (query_str == NULL) {
-   

[PATCH v2 01/10] cli: search: Rename options to context

2014-11-03 Thread Michal Sojka
Just text replacement, no other changes.
---
 notmuch-search.c | 142 +++
 1 file changed, 71 insertions(+), 71 deletions(-)

diff --git a/notmuch-search.c b/notmuch-search.c
index 6345fb6..2c47b80 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -42,7 +42,7 @@ typedef struct {
 int offset;
 int limit;
 int dupe;
-} search_options_t;
+} search_context_t;
 
 typedef struct {
 const char *name;
@@ -89,39 +89,39 @@ get_thread_query (notmuch_thread_t *thread,
 }
 
 static int
-do_search_threads (search_options_t *opt)
+do_search_threads (search_context_t *ctx)
 {
 notmuch_thread_t *thread;
 notmuch_threads_t *threads;
 notmuch_tags_t *tags;
-sprinter_t *format = opt-format;
+sprinter_t *format = ctx-format;
 time_t date;
 int i;
 
-if (opt-offset  0) {
-   opt-offset += notmuch_query_count_threads (opt-query);
-   if (opt-offset  0)
-   opt-offset = 0;
+if (ctx-offset  0) {
+   ctx-offset += notmuch_query_count_threads (ctx-query);
+   if (ctx-offset  0)
+   ctx-offset = 0;
 }
 
-threads = notmuch_query_search_threads (opt-query);
+threads = notmuch_query_search_threads (ctx-query);
 if (threads == NULL)
return 1;
 
 format-begin_list (format);
 
 for (i = 0;
-notmuch_threads_valid (threads)  (opt-limit  0 || i  opt-offset 
+ opt-limit);
+notmuch_threads_valid (threads)  (ctx-limit  0 || i  ctx-offset 
+ ctx-limit);
 notmuch_threads_move_to_next (threads), i++)
 {
thread = notmuch_threads_get (threads);
 
-   if (i  opt-offset) {
+   if (i  ctx-offset) {
notmuch_thread_destroy (thread);
continue;
}
 
-   if (opt-output == OUTPUT_THREADS) {
+   if (ctx-output == OUTPUT_THREADS) {
format-set_prefix (format, thread);
format-string (format,
notmuch_thread_get_thread_id (thread));
@@ -138,7 +138,7 @@ do_search_threads (search_options_t *opt)
 
format-begin_map (format);
 
-   if (opt-sort == NOTMUCH_SORT_OLDEST_FIRST)
+   if (ctx-sort == NOTMUCH_SORT_OLDEST_FIRST)
date = notmuch_thread_get_oldest_date (thread);
else
date = notmuch_thread_get_newest_date (thread);
@@ -230,11 +230,11 @@ do_search_threads (search_options_t *opt)
 }
 
 static void
-print_mailbox (const search_options_t *opt, const mailbox_t *mailbox)
+print_mailbox (const search_context_t *ctx, const mailbox_t *mailbox)
 {
 const char *name = mailbox-name;
 const char *addr = mailbox-addr;
-sprinter_t *format = opt-format;
+sprinter_t *format = ctx-format;
 InternetAddress *ia = internet_address_mailbox_new (name, addr);
 char *name_addr;
 
@@ -263,7 +263,7 @@ print_mailbox (const search_options_t *opt, const mailbox_t 
*mailbox)
 
 /* Print addresses from InternetAddressList.  */
 static void
-process_address_list (const search_options_t *opt, InternetAddressList *list)
+process_address_list (const search_context_t *ctx, InternetAddressList *list)
 {
 InternetAddress *address;
 int i;
@@ -279,7 +279,7 @@ process_address_list (const search_options_t *opt, 
InternetAddressList *list)
if (group_list == NULL)
continue;
 
-   process_address_list (opt, group_list);
+   process_address_list (ctx, group_list);
} else {
InternetAddressMailbox *mailbox = INTERNET_ADDRESS_MAILBOX 
(address);
mailbox_t mbx = {
@@ -287,14 +287,14 @@ process_address_list (const search_options_t *opt, 
InternetAddressList *list)
.addr = internet_address_mailbox_get_addr (mailbox),
};
 
-   print_mailbox (opt, mbx);
+   print_mailbox (ctx, mbx);
}
 }
 }
 
 /* Print addresses from a message header.  */
 static void
-process_address_header (const search_options_t *opt, const char *value)
+process_address_header (const search_context_t *ctx, const char *value)
 {
 InternetAddressList *list;
 
@@ -305,7 +305,7 @@ process_address_header (const search_options_t *opt, const 
char *value)
 if (list == NULL)
return;
 
-process_address_list (opt, list);
+process_address_list (ctx, list);
 
 g_object_unref (list);
 }
@@ -329,36 +329,36 @@ _count_filenames (notmuch_message_t *message)
 }
 
 static int
-do_search_messages (search_options_t *opt)
+do_search_messages (search_context_t *ctx)
 {
 notmuch_message_t *message;
 notmuch_messages_t *messages;
 notmuch_filenames_t *filenames;
-sprinter_t *format = opt-format;
+sprinter_t *format = ctx-format;
 int i;
 
-if (opt-offset  0) {
-   opt-offset += notmuch_query_count_messages (opt-query);
-   if (opt-offset  0)
-   opt-offset = 0;
+if (ctx-offset  0) {
+   ctx-offset += notmuch_query_count_messages (ctx-query);
+   if 

[PATCH v2 00/10] notmuch address command

2014-11-03 Thread Michal Sojka
Hi all,

this is v2 of notmuch address patchset. It obsoletes [1].

Don't be scared by the number of patches. Most of them are trivial
refactoring. Patches 1-4 refactor the code so that notmuch search
command is easier to split. Patch 5 is Jani's hierarchical command
line parsing patch. Patch 6 splits search functionality to new address
command. Patch 7 is minor refactoring. Patches 8-10 correspond to
patches 5-7 in the original notmuch search
--output=sender/recipients patch series [2].

Changes from v1:

- Rebased to current master (conflicted with Jani's notmuch search
  --duplicate=N with --output=messages patch)
- Fixed printing of false Unrecognized option error message in
  hierarchical command line parser.

Regards,
-Michal

[1] id:1414889400-30977-1-git-send-email-sojk...@fel.cvut.cz
[2] id:1414792441-29555-1-git-send-email-sojk...@fel.cvut.cz


Jani Nikula (1):
  cli: add support for hierarchical command line option arrays

Michal Sojka (9):
  cli: search: Rename options to context
  cli: search: Move more variables into search_context_t
  cli: search: Convert ctx. to ctx-
  cli: search: Split notmuch_search_command to smaller functions
  cli: Introduce notmuch address command
  cli: search: Convert --output to keyword argument
  cli: address: Do not output duplicate addresses
  cli: address: Add --output=count
  cli: address: Add --filter-by option to configure address filtering

 command-line-arguments.c   |  16 +-
 command-line-arguments.h   |   1 +
 completion/notmuch-completion.bash |  48 +++-
 completion/notmuch-completion.zsh  |  11 +-
 doc/man1/notmuch-address.rst   | 140 
 doc/man1/notmuch-search.rst|  21 +-
 doc/man1/notmuch.rst   |   7 +-
 notmuch-client.h   |   3 +
 notmuch-search.c   | 454 +
 notmuch.c  |   2 +
 test/T095-address.sh   | 148 
 test/T097-address-filter-by.sh |  73 ++
 12 files changed, 751 insertions(+), 173 deletions(-)
 create mode 100644 doc/man1/notmuch-address.rst
 create mode 100755 test/T095-address.sh
 create mode 100755 test/T097-address-filter-by.sh

-- 
2.1.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v2 08/10] cli: address: Do not output duplicate addresses

2014-11-03 Thread Michal Sojka
This filters out duplicate addresses from address command output.

It also also adds tests for the address command.

The code here is an extended version of a patch from Jani Nikula.
---
 doc/man1/notmuch-address.rst |   2 +-
 notmuch-search.c |  40 -
 test/T095-address.sh | 100 +++
 3 files changed, 140 insertions(+), 2 deletions(-)
 create mode 100755 test/T095-address.sh

diff --git a/doc/man1/notmuch-address.rst b/doc/man1/notmuch-address.rst
index 8109f11..96512b7 100644
--- a/doc/man1/notmuch-address.rst
+++ b/doc/man1/notmuch-address.rst
@@ -11,7 +11,7 @@ DESCRIPTION
 ===
 
 Search for messages matching the given search terms, and display the
-addresses from them.
+addresses from them. Duplicate addresses are filtered out.
 
 See **notmuch-search-terms(7)** for details of the supported syntax for
 search-terms.
diff --git a/notmuch-search.c b/notmuch-search.c
index 402e860..741702a 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -53,6 +53,7 @@ typedef struct {
 int offset;
 int limit;
 int dupe;
+GHashTable *addresses;
 } search_context_t;
 
 typedef struct {
@@ -240,6 +241,27 @@ do_search_threads (search_context_t *ctx)
 return 0;
 }
 
+/* Returns TRUE iff name and addr is duplicate. */
+static notmuch_bool_t
+is_duplicate (const search_context_t *ctx, const char *name, const char *addr)
+{
+notmuch_bool_t duplicate;
+char *key;
+
+key = talloc_asprintf (ctx-format, %s %s, name, addr);
+if (! key)
+   return FALSE;
+
+duplicate = g_hash_table_lookup_extended (ctx-addresses, key, NULL, NULL);
+
+if (! duplicate)
+   g_hash_table_insert (ctx-addresses, key, NULL);
+else
+   talloc_free (key);
+
+return duplicate;
+}
+
 static void
 print_mailbox (const search_context_t *ctx, const mailbox_t *mailbox)
 {
@@ -274,7 +296,8 @@ print_mailbox (const search_context_t *ctx, const mailbox_t 
*mailbox)
 
 /* Print addresses from InternetAddressList.  */
 static void
-process_address_list (const search_context_t *ctx, InternetAddressList *list)
+process_address_list (const search_context_t *ctx,
+ InternetAddressList *list)
 {
 InternetAddress *address;
 int i;
@@ -298,6 +321,9 @@ process_address_list (const search_context_t *ctx, 
InternetAddressList *list)
.addr = internet_address_mailbox_get_addr (mailbox),
};
 
+   if (is_duplicate (ctx, mbx.name, mbx.addr))
+   continue;
+
print_mailbox (ctx, mbx);
}
 }
@@ -321,6 +347,12 @@ process_address_header (const search_context_t *ctx, const 
char *value)
 g_object_unref (list);
 }
 
+static void
+_my_talloc_free_for_g_hash (void *ptr)
+{
+talloc_free (ptr);
+}
+
 static int
 _count_filenames (notmuch_message_t *message)
 {
@@ -669,8 +701,14 @@ notmuch_address_command (notmuch_config_t *config, int 
argc, char *argv[])
 argc - opt_index, argv + opt_index))
return EXIT_FAILURE;
 
+ctx-addresses = g_hash_table_new_full (g_str_hash, g_str_equal,
+   _my_talloc_free_for_g_hash, NULL);
+
 ret = do_search_messages (ctx);
 
+g_hash_table_unref (ctx-addresses);
+
+
 _notmuch_search_cleanup (ctx);
 
 return ret ? EXIT_FAILURE : EXIT_SUCCESS;
diff --git a/test/T095-address.sh b/test/T095-address.sh
new file mode 100755
index 000..8a256d2
--- /dev/null
+++ b/test/T095-address.sh
@@ -0,0 +1,100 @@
+#!/usr/bin/env bash
+test_description='notmuch address in several variants'
+. ./test-lib.sh
+
+add_email_corpus
+
+test_begin_subtest --output=sender
+notmuch address --output=sender '*' OUTPUT
+cat EOF EXPECTED
+François Boulogne boulogn...@gmail.com
+Olivier Berger olivier.ber...@it-sudparis.eu
+Chris Wilson ch...@chris-wilson.co.uk
+Carl Worth cwo...@cworth.org
+Alexander Botero-Lowry alex.boterolo...@gmail.com
+Keith Packard kei...@keithp.com
+Jjgod Jiang gzjj...@gmail.com
+Rolland Santimano rollandsantim...@yahoo.com
+Jan Janak j...@ryngle.com
+Stewart Smith stew...@flamingspork.com
+Lars Kellogg-Stedman l...@seas.harvard.edu
+Alex Botero-Lowry alex.boterolo...@gmail.com
+Ingmar Vanhassel ing...@exherbo.org
+Aron Griffis agrif...@n01se.net
+Adrian Perez de Castro ape...@igalia.com
+Israel Herraiz i...@herraiz.org
+Mikhail Gusarov dotted...@dottedmag.net
+EOF
+test_expect_equal_file OUTPUT EXPECTED
+
+test_begin_subtest --output=sender --format=json
+notmuch address --output=sender --format=json '*' OUTPUT
+cat EOF EXPECTED
+[{name: François Boulogne, address: boulogn...@gmail.com, name-addr: 
François Boulogne boulogn...@gmail.com},
+{name: Olivier Berger, address: olivier.ber...@it-sudparis.eu, 
name-addr: Olivier Berger olivier.ber...@it-sudparis.eu},
+{name: Chris Wilson, address: ch...@chris-wilson.co.uk, name-addr: 
Chris Wilson ch...@chris-wilson.co.uk},
+{name: Carl Worth, address: cwo...@cworth.org, 

[PATCH v2 09/10] cli: address: Add --output=count

2014-11-03 Thread Michal Sojka
This output prints how many times was each address encountered during
search.
---
 completion/notmuch-completion.bash |  2 +-
 completion/notmuch-completion.zsh  |  2 +-
 doc/man1/notmuch-address.rst   |  7 ++
 notmuch-search.c   | 49 --
 test/T095-address.sh   | 48 +
 5 files changed, 99 insertions(+), 9 deletions(-)

diff --git a/completion/notmuch-completion.bash 
b/completion/notmuch-completion.bash
index 94ea2d5..db152f3 100644
--- a/completion/notmuch-completion.bash
+++ b/completion/notmuch-completion.bash
@@ -332,7 +332,7 @@ _notmuch_address()
return
;;
--output)
-   COMPREPLY=( $( compgen -W sender recipients -- ${cur} ) )
+   COMPREPLY=( $( compgen -W sender recipients count -- ${cur} ) )
return
;;
--sort)
diff --git a/completion/notmuch-completion.zsh 
b/completion/notmuch-completion.zsh
index c606b75..8968562 100644
--- a/completion/notmuch-completion.zsh
+++ b/completion/notmuch-completion.zsh
@@ -61,7 +61,7 @@ _notmuch_address()
 {
   _arguments -s : \
 '--sort=[sort results]:sorting:((newest-first\:reverse chronological 
order oldest-first\:chronological order))' \
-'--output=[select what to output]:output:((sender recipients))'
+'--output=[select what to output]:output:((sender recipients count))'
 }
 
 _notmuch()
diff --git a/doc/man1/notmuch-address.rst b/doc/man1/notmuch-address.rst
index 96512b7..18473a7 100644
--- a/doc/man1/notmuch-address.rst
+++ b/doc/man1/notmuch-address.rst
@@ -48,6 +48,13 @@ Supported options for **address** include
 Output all addresses from the *To*, *Cc* and *Bcc*
 headers.
 
+   **count**
+   Print the count of how many times was the address
+   encountered during search.
+
+   Note: With this option, addresses are printed only after
+   the whole search is finished. This may take long time.
+
 ``--sort=``\ (**newest-first**\ \|\ **oldest-first**)
 This option can be used to present results in either
 chronological order (**oldest-first**) or reverse chronological
diff --git a/notmuch-search.c b/notmuch-search.c
index 741702a..d99e530 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -33,6 +33,7 @@ typedef enum {
 /* Address command */
 OUTPUT_SENDER  = 1  5,
 OUTPUT_RECIPIENTS  = 1  6,
+OUTPUT_COUNT   = 1  7,
 } output_t;
 
 typedef enum {
@@ -59,6 +60,7 @@ typedef struct {
 typedef struct {
 const char *name;
 const char *addr;
+int count;
 } mailbox_t;
 
 /* Return two stable query strings that identify exactly the matched
@@ -247,17 +249,24 @@ is_duplicate (const search_context_t *ctx, const char 
*name, const char *addr)
 {
 notmuch_bool_t duplicate;
 char *key;
+mailbox_t *mailbox;
 
 key = talloc_asprintf (ctx-format, %s %s, name, addr);
 if (! key)
return FALSE;
 
-duplicate = g_hash_table_lookup_extended (ctx-addresses, key, NULL, NULL);
+duplicate = g_hash_table_lookup_extended (ctx-addresses, key, NULL, 
(gpointer)mailbox);
 
-if (! duplicate)
-   g_hash_table_insert (ctx-addresses, key, NULL);
-else
+if (! duplicate) {
+   mailbox = talloc (ctx-format, mailbox_t);
+   mailbox-name = talloc_strdup (mailbox, name);
+   mailbox-addr = talloc_strdup (mailbox, addr);
+   mailbox-count = 1;
+   g_hash_table_insert (ctx-addresses, key, mailbox);
+} else {
+   mailbox-count++;
talloc_free (key);
+}
 
 return duplicate;
 }
@@ -267,6 +276,7 @@ print_mailbox (const search_context_t *ctx, const mailbox_t 
*mailbox)
 {
 const char *name = mailbox-name;
 const char *addr = mailbox-addr;
+int count = mailbox-count;
 sprinter_t *format = ctx-format;
 InternetAddress *ia = internet_address_mailbox_new (name, addr);
 char *name_addr;
@@ -276,6 +286,10 @@ print_mailbox (const search_context_t *ctx, const 
mailbox_t *mailbox)
 name_addr = internet_address_to_string (ia, FALSE);
 
 if (format-is_text_printer) {
+   if (count  0) {
+   format-integer (format, count);
+   format-string (format, \t);
+   }
format-string (format, name_addr);
format-separator (format);
 } else {
@@ -286,6 +300,10 @@ print_mailbox (const search_context_t *ctx, const 
mailbox_t *mailbox)
format-string (format, addr);
format-map_key (format, name-addr);
format-string (format, name_addr);
+   if (count  0) {
+   format-map_key (format, count);
+   format-integer (format, count);
+   }
format-end (format);
format-separator (format);
 }
@@ -294,7 +312,7 @@ print_mailbox (const search_context_t *ctx, const mailbox_t 
*mailbox)
 g_free (name_addr);
 }
 
-/* Print addresses from InternetAddressList.  */
+/* Print or prepare for printing 

[PATCH v2 05/10] cli: add support for hierarchical command line option arrays

2014-11-03 Thread Michal Sojka
From: Jani Nikula j...@nikula.org

NOTMUCH_OPT_INHERIT expects a notmuch_opt_desc_t * pointer in
output_var.

The Unrecognized option message was moved out of parse_option() to
not be emitted twice or when parsing a non-inherited option.
---
 command-line-arguments.c | 16 +---
 command-line-arguments.h |  1 +
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/command-line-arguments.c b/command-line-arguments.c
index c6f7269..de6b453 100644
--- a/command-line-arguments.c
+++ b/command-line-arguments.c
@@ -122,16 +122,18 @@ parse_position_arg (const char *arg_str, int 
pos_arg_index,
  */
 
 notmuch_bool_t
-parse_option (const char *arg,
- const notmuch_opt_desc_t *options) {
-
-assert(arg);
+parse_option (const char *_arg, const notmuch_opt_desc_t *options)
+{
+assert(_arg);
 assert(options);
 
-arg += 2;
-
+const char *arg = _arg + 2; /* _arg starts with -- */
 const notmuch_opt_desc_t *try;
 for (try = options; try-opt_type != NOTMUCH_OPT_END; try++) {
+   if (try-opt_type == NOTMUCH_OPT_INHERIT 
+   parse_option (_arg, try-output_var))
+   return TRUE;
+
if (! try-name)
continue;
 
@@ -170,7 +172,6 @@ parse_option (const char *arg,
/*UNREACHED*/
}
 }
-fprintf (stderr, Unrecognized option: --%s\n, arg);
 return FALSE;
 }
 
@@ -201,6 +202,7 @@ parse_arguments (int argc, char **argv,
if (more_args) {
opt_index++;
} else {
+   fprintf (stderr, Unrecognized option: %s\n, argv[opt_index]);
opt_index = -1;
}
 
diff --git a/command-line-arguments.h b/command-line-arguments.h
index 6444129..309aaf2 100644
--- a/command-line-arguments.h
+++ b/command-line-arguments.h
@@ -5,6 +5,7 @@
 
 enum notmuch_opt_type {
 NOTMUCH_OPT_END = 0,
+NOTMUCH_OPT_INHERIT,   /* another options table */
 NOTMUCH_OPT_BOOLEAN,   /* --verbose  */
 NOTMUCH_OPT_INT,   /* --frob=8   */
 NOTMUCH_OPT_KEYWORD,   /* --format=raw|json|text */
-- 
2.1.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


[PATCH v2 03/10] cli: search: Convert ctx. to ctx-

2014-11-03 Thread Michal Sojka
Mostly text replacement.
---
 notmuch-search.c | 81 
 1 file changed, 41 insertions(+), 40 deletions(-)

diff --git a/notmuch-search.c b/notmuch-search.c
index 3d2012b..6765a16 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -474,7 +474,7 @@ do_search_tags (const search_context_t *ctx)
 int
 notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
 {
-search_context_t ctx = {
+search_context_t search_context = {
.format_sel = NOTMUCH_FORMAT_TEXT,
.exclude = NOTMUCH_EXCLUDE_TRUE,
.sort = NOTMUCH_SORT_NEWEST_FIRST,
@@ -483,23 +483,24 @@ notmuch_search_command (notmuch_config_t *config, int 
argc, char *argv[])
.limit = -1, /* unlimited */
.dupe = -1,
 };
+search_context_t *ctx = search_context;
 char *query_str;
 int opt_index, ret;
 unsigned int i;
 
 notmuch_opt_desc_t options[] = {
-   { NOTMUCH_OPT_KEYWORD, ctx.sort, sort, 's',
+   { NOTMUCH_OPT_KEYWORD, ctx-sort, sort, 's',
  (notmuch_keyword_t []){ { oldest-first, NOTMUCH_SORT_OLDEST_FIRST },
  { newest-first, NOTMUCH_SORT_NEWEST_FIRST },
  { 0, 0 } } },
-   { NOTMUCH_OPT_KEYWORD, ctx.format_sel, format, 'f',
+   { NOTMUCH_OPT_KEYWORD, ctx-format_sel, format, 'f',
  (notmuch_keyword_t []){ { json, NOTMUCH_FORMAT_JSON },
  { sexp, NOTMUCH_FORMAT_SEXP },
  { text, NOTMUCH_FORMAT_TEXT },
  { text0, NOTMUCH_FORMAT_TEXT0 },
  { 0, 0 } } },
{ NOTMUCH_OPT_INT, notmuch_format_version, format-version, 0, 0 },
-   { NOTMUCH_OPT_KEYWORD_FLAGS, ctx.output, output, 'o',
+   { NOTMUCH_OPT_KEYWORD_FLAGS, ctx-output, output, 'o',
  (notmuch_keyword_t []){ { summary, OUTPUT_SUMMARY },
  { threads, OUTPUT_THREADS },
  { messages, OUTPUT_MESSAGES },
@@ -508,15 +509,15 @@ notmuch_search_command (notmuch_config_t *config, int 
argc, char *argv[])
  { files, OUTPUT_FILES },
  { tags, OUTPUT_TAGS },
  { 0, 0 } } },
-{ NOTMUCH_OPT_KEYWORD, ctx.exclude, exclude, 'x',
+{ NOTMUCH_OPT_KEYWORD, ctx-exclude, exclude, 'x',
   (notmuch_keyword_t []){ { true, NOTMUCH_EXCLUDE_TRUE },
   { false, NOTMUCH_EXCLUDE_FALSE },
   { flag, NOTMUCH_EXCLUDE_FLAG },
   { all, NOTMUCH_EXCLUDE_ALL },
   { 0, 0 } } },
-   { NOTMUCH_OPT_INT, ctx.offset, offset, 'O', 0 },
-   { NOTMUCH_OPT_INT, ctx.limit, limit, 'L', 0  },
-   { NOTMUCH_OPT_INT, ctx.dupe, duplicate, 'D', 0  },
+   { NOTMUCH_OPT_INT, ctx-offset, offset, 'O', 0 },
+   { NOTMUCH_OPT_INT, ctx-limit, limit, 'L', 0  },
+   { NOTMUCH_OPT_INT, ctx-dupe, duplicate, 'D', 0  },
{ 0, 0, 0, 0, 0 }
 };
 
@@ -524,31 +525,31 @@ notmuch_search_command (notmuch_config_t *config, int 
argc, char *argv[])
 if (opt_index  0)
return EXIT_FAILURE;
 
-if (! ctx.output)
-   ctx.output = OUTPUT_SUMMARY;
+if (! ctx-output)
+   ctx-output = OUTPUT_SUMMARY;
 
-if (ctx.output != OUTPUT_FILES  ctx.output != OUTPUT_MESSAGES 
-   ctx.dupe != -1) {
+if (ctx-output != OUTPUT_FILES  ctx-output != OUTPUT_MESSAGES 
+   ctx-dupe != -1) {
 fprintf (stderr, Error: --duplicate=N is only supported with 
--output=files and --output=messages.\n);
 return EXIT_FAILURE;
 }
 
-switch (ctx.format_sel) {
+switch (ctx-format_sel) {
 case NOTMUCH_FORMAT_TEXT:
-   ctx.format = sprinter_text_create (config, stdout);
+   ctx-format = sprinter_text_create (config, stdout);
break;
 case NOTMUCH_FORMAT_TEXT0:
-   if (ctx.output == OUTPUT_SUMMARY) {
+   if (ctx-output == OUTPUT_SUMMARY) {
fprintf (stderr, Error: --format=text0 is not compatible with 
--output=summary.\n);
return EXIT_FAILURE;
}
-   ctx.format = sprinter_text0_create (config, stdout);
+   ctx-format = sprinter_text0_create (config, stdout);
break;
 case NOTMUCH_FORMAT_JSON:
-   ctx.format = sprinter_json_create (config, stdout);
+   ctx-format = sprinter_json_create (config, stdout);
break;
 case NOTMUCH_FORMAT_SEXP:
-   ctx.format = sprinter_sexp_create (config, stdout);
+   ctx-format = sprinter_sexp_create (config, stdout);
break;
 default:
/* this should never happen */
@@ -558,10 +559,10 @@ notmuch_search_command (notmuch_config_t *config, int 
argc, char *argv[])
 notmuch_exit_if_unsupported_format ();
 
 if (notmuch_database_open (notmuch_config_get_database_path (config),
-

[PATCH v2 07/10] cli: search: Convert --output to keyword argument

2014-11-03 Thread Michal Sojka
Now, when address related outputs are in a separate command, it makes
no sense to combine multiple --output options in search command line.
Using switch statement to handle different outputs is more readable
than a series of if statements.
---
 doc/man1/notmuch-search.rst |  3 ---
 notmuch-search.c| 25 +
 2 files changed, 13 insertions(+), 15 deletions(-)

diff --git a/doc/man1/notmuch-search.rst b/doc/man1/notmuch-search.rst
index 65df288..0cc2911 100644
--- a/doc/man1/notmuch-search.rst
+++ b/doc/man1/notmuch-search.rst
@@ -78,9 +78,6 @@ Supported options for **search** include
 by null characters (--format=text0), as a JSON array
 (--format=json), or as an S-Expression list (--format=sexp).
 
-   This option can be given multiple times to combine different
-   outputs.
-
 ``--sort=``\ (**newest-first**\ \|\ **oldest-first**)
 This option can be used to present results in either
 chronological order (**oldest-first**) or reverse chronological
diff --git a/notmuch-search.c b/notmuch-search.c
index cbd84f5..402e860 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -593,7 +593,7 @@ notmuch_search_command (notmuch_config_t *config, int argc, 
char *argv[])
 int opt_index, ret;
 
 notmuch_opt_desc_t options[] = {
-   { NOTMUCH_OPT_KEYWORD_FLAGS, ctx-output, output, 'o',
+   { NOTMUCH_OPT_KEYWORD, ctx-output, output, 'o',
  (notmuch_keyword_t []){ { summary, OUTPUT_SUMMARY },
  { threads, OUTPUT_THREADS },
  { messages, OUTPUT_MESSAGES },
@@ -607,13 +607,11 @@ notmuch_search_command (notmuch_config_t *config, int 
argc, char *argv[])
{ 0, 0, 0, 0, 0 }
 };
 
+ctx-output = OUTPUT_SUMMARY;
 opt_index = parse_arguments (argc, argv, options, 1);
 if (opt_index  0)
return EXIT_FAILURE;
 
-if (! ctx-output)
-   ctx-output = OUTPUT_SUMMARY;
-
 if (ctx-output != OUTPUT_FILES  ctx-output != OUTPUT_MESSAGES 
ctx-dupe != -1) {
 fprintf (stderr, Error: --duplicate=N is only supported with 
--output=files and --output=messages.\n);
@@ -624,17 +622,20 @@ notmuch_search_command (notmuch_config_t *config, int 
argc, char *argv[])
 argc - opt_index, argv + opt_index))
return EXIT_FAILURE;
 
-if (ctx-output == OUTPUT_SUMMARY ||
-   ctx-output == OUTPUT_THREADS)
+switch (ctx-output) {
+case OUTPUT_SUMMARY:
+case OUTPUT_THREADS:
ret = do_search_threads (ctx);
-else if (ctx-output == OUTPUT_MESSAGES ||
-ctx-output == OUTPUT_FILES)
+   break;
+case OUTPUT_MESSAGES:
+case OUTPUT_FILES:
ret = do_search_messages (ctx);
-else if (ctx-output == OUTPUT_TAGS)
+   break;
+case OUTPUT_TAGS:
ret = do_search_tags (ctx);
-else {
-   fprintf (stderr, Error: the combination of outputs is not 
supported.\n);
-   ret = 1;
+   break;
+default:
+   INTERNAL_ERROR (Unexpected output);
 }
 
 _notmuch_search_cleanup (ctx);
-- 
2.1.1

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH v2 01/10] cli: search: Rename options to context

2014-11-03 Thread David Bremner
Michal Sojka sojk...@fel.cvut.cz writes:

 Just text replacement, no other changes.

I agree that the actual change is trivial, but the commit message
could/should hint why it is being done.
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH v2 03/10] cli: search: Convert ctx. to ctx-

2014-11-03 Thread David Bremner
Michal Sojka sojk...@fel.cvut.cz writes:

 Mostly text replacement.

Here I'd like to know why we are moving from a struct to a pointer to
struct.

It would be a bonus to hightlight any non text-replacement.
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH v2 05/10] cli: add support for hierarchical command line option arrays

2014-11-03 Thread David Bremner
Michal Sojka sojk...@fel.cvut.cz writes:

 From: Jani Nikula j...@nikula.org

 NOTMUCH_OPT_INHERIT expects a notmuch_opt_desc_t * pointer in
 output_var.

At the risk of bikeshedding, what about NOTMUCH_OPT_RECURSE instead of
_INHERIT?
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH v2 05/10] cli: add support for hierarchical command line option arrays

2014-11-03 Thread David Bremner
David Bremner da...@tethera.net writes:

 Michal Sojka sojk...@fel.cvut.cz writes:

 From: Jani Nikula j...@nikula.org

 NOTMUCH_OPT_INHERIT expects a notmuch_opt_desc_t * pointer in
 output_var.

 At the risk of bikeshedding, what about NOTMUCH_OPT_RECURSE instead of
 _INHERIT?

Hrm. Now that I read the next patch, I retract my suggestion.

d
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH v2 06/10] cli: Introduce notmuch address command

2014-11-03 Thread David Bremner
Michal Sojka sojk...@fel.cvut.cz writes:

 +{
 +local cur prev words cword split
 +_init_completion -s || return
 +
 +$split 
 +case ${prev} in
 + --format)
 + COMPREPLY=( $( compgen -W json sexp text text0 -- ${cur} ) )
 + return
 + ;;
 + --output)
 + COMPREPLY=( $( compgen -W sender recipients -- ${cur} ) )
 + return
 + ;;
 + --sort)
 + COMPREPLY=( $( compgen -W newest-first oldest-first -- ${cur} ) 
 )
 + return
 + ;;
 + --exclude)
 + COMPREPLY=( $( compgen -W true false flag all -- ${cur} ) )
 + return
 + ;;
 +esac
 +
 +! $split 
 +case ${cur} in
 + -*)
 + local options=--format= --output= --sort= --exclude=
 + compopt -o nospace
 + COMPREPLY=( $(compgen -W $options -- ${cur}) )
 + ;;
 + *)
 + _notmuch_search_terms
 + ;;
 +esac
 +}
 +

I am reminded that we have no tests for shell completion stuff, which
seems pretty fragile.

 +
 +``--format=``\ (**json**\ \|\ **sexp**\ \|\ **text**\ \|\ **text0**)
 +Presents the results in either JSON, S-Expressions, newline
 +character separated plain-text (default), or null character
 +separated plain-text (compatible with **xargs(1)** -0 option
 +where available).
 +
 +``--format-version=N``
 +Use the specified structured output format version. This is
 +intended for programs that invoke **notmuch(1)** internally. If
 +omitted, the latest supported version will be used.
 +


I wonder if at some point we should have a notmuch-output-formats.7 page.


 +``--exclude=(true|false|all|flag)``
 +A message is called excluded if it matches at least one tag in
 +search.tag\_exclude that does not appear explicitly in the
 +search terms. This option specifies whether to omit excluded
 +messages in the search process.

Similarly for excludes.  I'm ok with the duplication for now, and I can
see an argument for not making the user chase references.

___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch


Re: [PATCH v2 08/10] cli: address: Do not output duplicate addresses

2014-11-03 Thread David Bremner
Michal Sojka sojk...@fel.cvut.cz writes:

  
 +/* Returns TRUE iff name and addr is duplicate. */

If you're revising this patch, it would be good to mention the side
effect of this function.

 -process_address_list (const search_context_t *ctx, InternetAddressList *list)
 +process_address_list (const search_context_t *ctx,
 +   InternetAddressList *list)

It probably doesn't make any difference, but this looks like a needless
whitespace change.

This function definitely needs some comment / pointer to
documention. And probably not to have _my in the name.

 +static void
 +_my_talloc_free_for_g_hash (void *ptr)
 +{
 +talloc_free (ptr);
 +}
 +

I don't understand the name of the next subtest

 +test_begin_subtest No --output
 +notmuch address --output=sender --output=recipients '*' OUTPUT
 +# Use EXPECTED from previous subtest
 +test_expect_equal_file OUTPUT EXPECTED
 +
 +
 +test_done

nitpick, extra blank lines

So, AIUI, this is all of the series proposed for 0.19. It looks close to
OK to me, modulo some minor style nits. One anonymous commentator on
IRC mentioned the use of module scope variables, I guess in patch
6/10. I'm not sure of a better solution, but it's true in a perfect
world we wouldn't have module local state.

d
___
notmuch mailing list
notmuch@notmuchmail.org
http://notmuchmail.org/mailman/listinfo/notmuch