[RFC PATCH] cli: add --remove-all option to "notmuch tag"

2012-12-16 Thread Jani Nikula
On Sun, 16 Dec 2012, Mark Walters  wrote:
> On Mon, 03 Dec 2012, Jani Nikula  wrote:
>> Add --remove-all option to "notmuch tag" to remove all tags matching
>> query before applying the tag changes. This allows removal and
>> unconditional setting of the tags of a message:
>>
>> $ notmuch tag --remove-all id:foo at example.com
>> $ notmuch tag --remove-all +foo +bar id:foo at example.com
>>
>> without having to resort to the complicated (and still quoting broken):
>>
>> $ notmuch tag $(notmuch search --output=tags '*' | sed 's/^/-/') id:foo at 
>> example.com
>> $ notmuch tag $(notmuch search --output=tags '*' | sed 's/^/-/') +foo +bar 
>> id:foo at example.com
>>
>> ---
>>
>> It's completely untested...
>>
>> This is on top of David's batch tagging branch new-tagging at
>> git://pivot.cs.unb.ca/notmuch.git
>>
>> If there's interest, I'll spin a new version with tests and man page
>> changes after David's stuff has been merged.
>
> I like this: the possibility of setting the tags to something seems
> nice. 

Thanks for the feedback; I'll rebase once we're done with the batch
tagging stuff.

> I am not very keen on the option name but don't have anything much
> better: maybe --remove-all-first or --set-to? 

I still like --remove-all, and, like you say, those aren't much
better. But we can bikeshed this later. ;)

> Incidentally, does this (or should this) give an error if the user calls
> --remove-all with -some_tag (as opposed to +some_tag)?

I think not. There are no errors if you do -foo -foo, or remove a tag
that isn't in any of the messages matching query.

BR,
Jani.


>
> Best wishes
>
> Mark
>
>
>> ---
>>  notmuch-tag.c |   32 
>>  1 file changed, 20 insertions(+), 12 deletions(-)
>>
>> diff --git a/notmuch-tag.c b/notmuch-tag.c
>> index e4fca67..67624cc 100644
>> --- a/notmuch-tag.c
>> +++ b/notmuch-tag.c
>> @@ -119,12 +119,15 @@ tag_query (void *ctx, notmuch_database_t *notmuch, 
>> const char *query_string,
>>  notmuch_messages_t *messages;
>>  notmuch_message_t *message;
>>  
>> -/* Optimize the query so it excludes messages that already have
>> - * the specified set of tags. */
>> -query_string = _optimize_tag_query (ctx, query_string, tag_ops);
>> -if (query_string == NULL) {
>> -fprintf (stderr, "Out of memory.\n");
>> -return 1;
>> +if (! (flags & TAG_FLAG_REMOVE_ALL)) {
>> +/* Optimize the query so it excludes messages that already
>> + * have the specified set of tags. */
>> +query_string = _optimize_tag_query (ctx, query_string, tag_ops);
>> +if (query_string == NULL) {
>> +fprintf (stderr, "Out of memory.\n");
>> +return 1;
>> +}
>> +flags |= TAG_FLAG_PRE_OPTIMIZED;
>>  }
>>  
>>  query = notmuch_query_create (notmuch, query_string);
>> @@ -140,7 +143,7 @@ tag_query (void *ctx, notmuch_database_t *notmuch, const 
>> char *query_string,
>>   notmuch_messages_valid (messages) && ! interrupted;
>>   notmuch_messages_move_to_next (messages)) {
>>  message = notmuch_messages_get (messages);
>> -tag_op_list_apply (message, tag_ops, flags | TAG_FLAG_PRE_OPTIMIZED);
>> +tag_op_list_apply (message, tag_ops, flags);
>>  notmuch_message_destroy (message);
>>  }
>>  
>> @@ -157,8 +160,9 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
>>  notmuch_config_t *config;
>>  notmuch_database_t *notmuch;
>>  struct sigaction action;
>> -tag_op_flag_t synchronize_flags = TAG_FLAG_NONE;
>> +tag_op_flag_t flags = TAG_FLAG_NONE;
>>  notmuch_bool_t batch = FALSE;
>> +notmuch_bool_t remove_all = FALSE;
>>  FILE *input = stdin;
>>  char *input_file_name = NULL;
>>  int i, opt_index;
>> @@ -174,6 +178,7 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
>>  notmuch_opt_desc_t options[] = {
>>  { NOTMUCH_OPT_BOOLEAN, , "batch", 0, 0 },
>>  { NOTMUCH_OPT_STRING, _file_name, "input", 'i', 0 },
>> +{ NOTMUCH_OPT_BOOLEAN, _all, "remove-all", 0, 0 },
>>  { 0, 0, 0, 0, 0 }
>>  };
>>  
>> @@ -230,7 +235,7 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
>>  }
>>  }
>>  
>> -if (tag_op_list_size (tag_ops) == 0) {
>> +if (tag_op_list_size (tag_ops) == 0 && !remove_all) {
>>  fprintf (stderr, "Error: 'notmuch tag' requires at least one tag to 
>> add or remove.\n");
>>  return 1;
>>  }
>> @@ -252,7 +257,10 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
>>  return 1;
>>  
>>  if (notmuch_config_get_maildir_synchronize_flags (config))
>> -synchronize_flags = TAG_FLAG_MAILDIR_SYNC;
>> +flags |= TAG_FLAG_MAILDIR_SYNC;
>> +
>> +if (remove_all)
>> +flags |= TAG_FLAG_REMOVE_ALL;
>>  
>>  if (batch) {
>>  
>> @@ -280,14 +288,14 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
>>  continue;
>>  
>>  if (ret < 0 || tag_query (ctx, notmuch, query_string,
>> -  

[RFC PATCH] cli: add --remove-all option to "notmuch tag"

2012-12-16 Thread Mark Walters

On Mon, 03 Dec 2012, Jani Nikula  wrote:
> Add --remove-all option to "notmuch tag" to remove all tags matching
> query before applying the tag changes. This allows removal and
> unconditional setting of the tags of a message:
>
> $ notmuch tag --remove-all id:foo at example.com
> $ notmuch tag --remove-all +foo +bar id:foo at example.com
>
> without having to resort to the complicated (and still quoting broken):
>
> $ notmuch tag $(notmuch search --output=tags '*' | sed 's/^/-/') id:foo at 
> example.com
> $ notmuch tag $(notmuch search --output=tags '*' | sed 's/^/-/') +foo +bar 
> id:foo at example.com
>
> ---
>
> It's completely untested...
>
> This is on top of David's batch tagging branch new-tagging at
> git://pivot.cs.unb.ca/notmuch.git
>
> If there's interest, I'll spin a new version with tests and man page
> changes after David's stuff has been merged.

I like this: the possibility of setting the tags to something seems
nice. 

I am not very keen on the option name but don't have anything much
better: maybe --remove-all-first or --set-to? 

Incidentally, does this (or should this) give an error if the user calls
--remove-all with -some_tag (as opposed to +some_tag)?

Best wishes

Mark


> ---
>  notmuch-tag.c |   32 
>  1 file changed, 20 insertions(+), 12 deletions(-)
>
> diff --git a/notmuch-tag.c b/notmuch-tag.c
> index e4fca67..67624cc 100644
> --- a/notmuch-tag.c
> +++ b/notmuch-tag.c
> @@ -119,12 +119,15 @@ tag_query (void *ctx, notmuch_database_t *notmuch, 
> const char *query_string,
>  notmuch_messages_t *messages;
>  notmuch_message_t *message;
>  
> -/* Optimize the query so it excludes messages that already have
> - * the specified set of tags. */
> -query_string = _optimize_tag_query (ctx, query_string, tag_ops);
> -if (query_string == NULL) {
> - fprintf (stderr, "Out of memory.\n");
> - return 1;
> +if (! (flags & TAG_FLAG_REMOVE_ALL)) {
> + /* Optimize the query so it excludes messages that already
> +  * have the specified set of tags. */
> + query_string = _optimize_tag_query (ctx, query_string, tag_ops);
> + if (query_string == NULL) {
> + fprintf (stderr, "Out of memory.\n");
> + return 1;
> + }
> + flags |= TAG_FLAG_PRE_OPTIMIZED;
>  }
>  
>  query = notmuch_query_create (notmuch, query_string);
> @@ -140,7 +143,7 @@ tag_query (void *ctx, notmuch_database_t *notmuch, const 
> char *query_string,
>notmuch_messages_valid (messages) && ! interrupted;
>notmuch_messages_move_to_next (messages)) {
>   message = notmuch_messages_get (messages);
> - tag_op_list_apply (message, tag_ops, flags | TAG_FLAG_PRE_OPTIMIZED);
> + tag_op_list_apply (message, tag_ops, flags);
>   notmuch_message_destroy (message);
>  }
>  
> @@ -157,8 +160,9 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
>  notmuch_config_t *config;
>  notmuch_database_t *notmuch;
>  struct sigaction action;
> -tag_op_flag_t synchronize_flags = TAG_FLAG_NONE;
> +tag_op_flag_t flags = TAG_FLAG_NONE;
>  notmuch_bool_t batch = FALSE;
> +notmuch_bool_t remove_all = FALSE;
>  FILE *input = stdin;
>  char *input_file_name = NULL;
>  int i, opt_index;
> @@ -174,6 +178,7 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
>  notmuch_opt_desc_t options[] = {
>   { NOTMUCH_OPT_BOOLEAN, , "batch", 0, 0 },
>   { NOTMUCH_OPT_STRING, _file_name, "input", 'i', 0 },
> + { NOTMUCH_OPT_BOOLEAN, _all, "remove-all", 0, 0 },
>   { 0, 0, 0, 0, 0 }
>  };
>  
> @@ -230,7 +235,7 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
>   }
>   }
>  
> - if (tag_op_list_size (tag_ops) == 0) {
> + if (tag_op_list_size (tag_ops) == 0 && !remove_all) {
>   fprintf (stderr, "Error: 'notmuch tag' requires at least one tag to 
> add or remove.\n");
>   return 1;
>   }
> @@ -252,7 +257,10 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
>   return 1;
>  
>  if (notmuch_config_get_maildir_synchronize_flags (config))
> - synchronize_flags = TAG_FLAG_MAILDIR_SYNC;
> + flags |= TAG_FLAG_MAILDIR_SYNC;
> +
> +if (remove_all)
> + flags |= TAG_FLAG_REMOVE_ALL;
>  
>  if (batch) {
>  
> @@ -280,14 +288,14 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
>   continue;
>  
>   if (ret < 0 || tag_query (ctx, notmuch, query_string,
> -   tag_ops, synchronize_flags))
> +   tag_ops, flags))
>   break;
>   }
>  
>   if (line)
>   free (line);
>  } else
> - ret = tag_query (ctx, notmuch, query_string, tag_ops, 
> synchronize_flags);
> + ret = tag_query (ctx, notmuch, query_string, tag_ops, flags);
>  
>  notmuch_database_destroy (notmuch);
>  
> -- 
> 1.7.10.4
>
> ___
> notmuch mailing 

Re: [RFC PATCH] cli: add --remove-all option to notmuch tag

2012-12-16 Thread Mark Walters

On Mon, 03 Dec 2012, Jani Nikula j...@nikula.org wrote:
 Add --remove-all option to notmuch tag to remove all tags matching
 query before applying the tag changes. This allows removal and
 unconditional setting of the tags of a message:

 $ notmuch tag --remove-all id:f...@example.com
 $ notmuch tag --remove-all +foo +bar id:f...@example.com

 without having to resort to the complicated (and still quoting broken):

 $ notmuch tag $(notmuch search --output=tags '*' | sed 's/^/-/') 
 id:f...@example.com
 $ notmuch tag $(notmuch search --output=tags '*' | sed 's/^/-/') +foo +bar 
 id:f...@example.com

 ---

 It's completely untested...

 This is on top of David's batch tagging branch new-tagging at
 git://pivot.cs.unb.ca/notmuch.git

 If there's interest, I'll spin a new version with tests and man page
 changes after David's stuff has been merged.

I like this: the possibility of setting the tags to something seems
nice. 

I am not very keen on the option name but don't have anything much
better: maybe --remove-all-first or --set-to? 

Incidentally, does this (or should this) give an error if the user calls
--remove-all with -some_tag (as opposed to +some_tag)?

Best wishes

Mark


 ---
  notmuch-tag.c |   32 
  1 file changed, 20 insertions(+), 12 deletions(-)

 diff --git a/notmuch-tag.c b/notmuch-tag.c
 index e4fca67..67624cc 100644
 --- a/notmuch-tag.c
 +++ b/notmuch-tag.c
 @@ -119,12 +119,15 @@ tag_query (void *ctx, notmuch_database_t *notmuch, 
 const char *query_string,
  notmuch_messages_t *messages;
  notmuch_message_t *message;
  
 -/* Optimize the query so it excludes messages that already have
 - * the specified set of tags. */
 -query_string = _optimize_tag_query (ctx, query_string, tag_ops);
 -if (query_string == NULL) {
 - fprintf (stderr, Out of memory.\n);
 - return 1;
 +if (! (flags  TAG_FLAG_REMOVE_ALL)) {
 + /* Optimize the query so it excludes messages that already
 +  * have the specified set of tags. */
 + query_string = _optimize_tag_query (ctx, query_string, tag_ops);
 + if (query_string == NULL) {
 + fprintf (stderr, Out of memory.\n);
 + return 1;
 + }
 + flags |= TAG_FLAG_PRE_OPTIMIZED;
  }
  
  query = notmuch_query_create (notmuch, query_string);
 @@ -140,7 +143,7 @@ tag_query (void *ctx, notmuch_database_t *notmuch, const 
 char *query_string,
notmuch_messages_valid (messages)  ! interrupted;
notmuch_messages_move_to_next (messages)) {
   message = notmuch_messages_get (messages);
 - tag_op_list_apply (message, tag_ops, flags | TAG_FLAG_PRE_OPTIMIZED);
 + tag_op_list_apply (message, tag_ops, flags);
   notmuch_message_destroy (message);
  }
  
 @@ -157,8 +160,9 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
  notmuch_config_t *config;
  notmuch_database_t *notmuch;
  struct sigaction action;
 -tag_op_flag_t synchronize_flags = TAG_FLAG_NONE;
 +tag_op_flag_t flags = TAG_FLAG_NONE;
  notmuch_bool_t batch = FALSE;
 +notmuch_bool_t remove_all = FALSE;
  FILE *input = stdin;
  char *input_file_name = NULL;
  int i, opt_index;
 @@ -174,6 +178,7 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
  notmuch_opt_desc_t options[] = {
   { NOTMUCH_OPT_BOOLEAN, batch, batch, 0, 0 },
   { NOTMUCH_OPT_STRING, input_file_name, input, 'i', 0 },
 + { NOTMUCH_OPT_BOOLEAN, remove_all, remove-all, 0, 0 },
   { 0, 0, 0, 0, 0 }
  };
  
 @@ -230,7 +235,7 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
   }
   }
  
 - if (tag_op_list_size (tag_ops) == 0) {
 + if (tag_op_list_size (tag_ops) == 0  !remove_all) {
   fprintf (stderr, Error: 'notmuch tag' requires at least one tag to 
 add or remove.\n);
   return 1;
   }
 @@ -252,7 +257,10 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
   return 1;
  
  if (notmuch_config_get_maildir_synchronize_flags (config))
 - synchronize_flags = TAG_FLAG_MAILDIR_SYNC;
 + flags |= TAG_FLAG_MAILDIR_SYNC;
 +
 +if (remove_all)
 + flags |= TAG_FLAG_REMOVE_ALL;
  
  if (batch) {
  
 @@ -280,14 +288,14 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
   continue;
  
   if (ret  0 || tag_query (ctx, notmuch, query_string,
 -   tag_ops, synchronize_flags))
 +   tag_ops, flags))
   break;
   }
  
   if (line)
   free (line);
  } else
 - ret = tag_query (ctx, notmuch, query_string, tag_ops, 
 synchronize_flags);
 + ret = tag_query (ctx, notmuch, query_string, tag_ops, flags);
  
  notmuch_database_destroy (notmuch);
  
 -- 
 1.7.10.4

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

Re: [RFC PATCH] cli: add --remove-all option to notmuch tag

2012-12-16 Thread Jani Nikula
On Sun, 16 Dec 2012, Mark Walters markwalters1...@gmail.com wrote:
 On Mon, 03 Dec 2012, Jani Nikula j...@nikula.org wrote:
 Add --remove-all option to notmuch tag to remove all tags matching
 query before applying the tag changes. This allows removal and
 unconditional setting of the tags of a message:

 $ notmuch tag --remove-all id:f...@example.com
 $ notmuch tag --remove-all +foo +bar id:f...@example.com

 without having to resort to the complicated (and still quoting broken):

 $ notmuch tag $(notmuch search --output=tags '*' | sed 's/^/-/') 
 id:f...@example.com
 $ notmuch tag $(notmuch search --output=tags '*' | sed 's/^/-/') +foo +bar 
 id:f...@example.com

 ---

 It's completely untested...

 This is on top of David's batch tagging branch new-tagging at
 git://pivot.cs.unb.ca/notmuch.git

 If there's interest, I'll spin a new version with tests and man page
 changes after David's stuff has been merged.

 I like this: the possibility of setting the tags to something seems
 nice. 

Thanks for the feedback; I'll rebase once we're done with the batch
tagging stuff.

 I am not very keen on the option name but don't have anything much
 better: maybe --remove-all-first or --set-to? 

I still like --remove-all, and, like you say, those aren't much
better. But we can bikeshed this later. ;)

 Incidentally, does this (or should this) give an error if the user calls
 --remove-all with -some_tag (as opposed to +some_tag)?

I think not. There are no errors if you do -foo -foo, or remove a tag
that isn't in any of the messages matching query.

BR,
Jani.



 Best wishes

 Mark


 ---
  notmuch-tag.c |   32 
  1 file changed, 20 insertions(+), 12 deletions(-)

 diff --git a/notmuch-tag.c b/notmuch-tag.c
 index e4fca67..67624cc 100644
 --- a/notmuch-tag.c
 +++ b/notmuch-tag.c
 @@ -119,12 +119,15 @@ tag_query (void *ctx, notmuch_database_t *notmuch, 
 const char *query_string,
  notmuch_messages_t *messages;
  notmuch_message_t *message;
  
 -/* Optimize the query so it excludes messages that already have
 - * the specified set of tags. */
 -query_string = _optimize_tag_query (ctx, query_string, tag_ops);
 -if (query_string == NULL) {
 -fprintf (stderr, Out of memory.\n);
 -return 1;
 +if (! (flags  TAG_FLAG_REMOVE_ALL)) {
 +/* Optimize the query so it excludes messages that already
 + * have the specified set of tags. */
 +query_string = _optimize_tag_query (ctx, query_string, tag_ops);
 +if (query_string == NULL) {
 +fprintf (stderr, Out of memory.\n);
 +return 1;
 +}
 +flags |= TAG_FLAG_PRE_OPTIMIZED;
  }
  
  query = notmuch_query_create (notmuch, query_string);
 @@ -140,7 +143,7 @@ tag_query (void *ctx, notmuch_database_t *notmuch, const 
 char *query_string,
   notmuch_messages_valid (messages)  ! interrupted;
   notmuch_messages_move_to_next (messages)) {
  message = notmuch_messages_get (messages);
 -tag_op_list_apply (message, tag_ops, flags | TAG_FLAG_PRE_OPTIMIZED);
 +tag_op_list_apply (message, tag_ops, flags);
  notmuch_message_destroy (message);
  }
  
 @@ -157,8 +160,9 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
  notmuch_config_t *config;
  notmuch_database_t *notmuch;
  struct sigaction action;
 -tag_op_flag_t synchronize_flags = TAG_FLAG_NONE;
 +tag_op_flag_t flags = TAG_FLAG_NONE;
  notmuch_bool_t batch = FALSE;
 +notmuch_bool_t remove_all = FALSE;
  FILE *input = stdin;
  char *input_file_name = NULL;
  int i, opt_index;
 @@ -174,6 +178,7 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
  notmuch_opt_desc_t options[] = {
  { NOTMUCH_OPT_BOOLEAN, batch, batch, 0, 0 },
  { NOTMUCH_OPT_STRING, input_file_name, input, 'i', 0 },
 +{ NOTMUCH_OPT_BOOLEAN, remove_all, remove-all, 0, 0 },
  { 0, 0, 0, 0, 0 }
  };
  
 @@ -230,7 +235,7 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
  }
  }
  
 -if (tag_op_list_size (tag_ops) == 0) {
 +if (tag_op_list_size (tag_ops) == 0  !remove_all) {
  fprintf (stderr, Error: 'notmuch tag' requires at least one tag to 
 add or remove.\n);
  return 1;
  }
 @@ -252,7 +257,10 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
  return 1;
  
  if (notmuch_config_get_maildir_synchronize_flags (config))
 -synchronize_flags = TAG_FLAG_MAILDIR_SYNC;
 +flags |= TAG_FLAG_MAILDIR_SYNC;
 +
 +if (remove_all)
 +flags |= TAG_FLAG_REMOVE_ALL;
  
  if (batch) {
  
 @@ -280,14 +288,14 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
  continue;
  
  if (ret  0 || tag_query (ctx, notmuch, query_string,
 -  tag_ops, synchronize_flags))
 +  tag_ops, flags))
  break;
  }
  
  if (line)
  free (line);
  } else
 -ret = tag_query (ctx, notmuch, 

[RFC PATCH] cli: add --remove-all option to "notmuch tag"

2012-12-04 Thread Jani Nikula
Add --remove-all option to "notmuch tag" to remove all tags matching
query before applying the tag changes. This allows removal and
unconditional setting of the tags of a message:

$ notmuch tag --remove-all id:foo at example.com
$ notmuch tag --remove-all +foo +bar id:foo at example.com

without having to resort to the complicated (and still quoting broken):

$ notmuch tag $(notmuch search --output=tags '*' | sed 's/^/-/') id:foo at 
example.com
$ notmuch tag $(notmuch search --output=tags '*' | sed 's/^/-/') +foo +bar 
id:foo at example.com

---

It's completely untested...

This is on top of David's batch tagging branch new-tagging at
git://pivot.cs.unb.ca/notmuch.git

If there's interest, I'll spin a new version with tests and man page
changes after David's stuff has been merged.
---
 notmuch-tag.c |   32 
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/notmuch-tag.c b/notmuch-tag.c
index e4fca67..67624cc 100644
--- a/notmuch-tag.c
+++ b/notmuch-tag.c
@@ -119,12 +119,15 @@ tag_query (void *ctx, notmuch_database_t *notmuch, const 
char *query_string,
 notmuch_messages_t *messages;
 notmuch_message_t *message;

-/* Optimize the query so it excludes messages that already have
- * the specified set of tags. */
-query_string = _optimize_tag_query (ctx, query_string, tag_ops);
-if (query_string == NULL) {
-   fprintf (stderr, "Out of memory.\n");
-   return 1;
+if (! (flags & TAG_FLAG_REMOVE_ALL)) {
+   /* Optimize the query so it excludes messages that already
+* have the specified set of tags. */
+   query_string = _optimize_tag_query (ctx, query_string, tag_ops);
+   if (query_string == NULL) {
+   fprintf (stderr, "Out of memory.\n");
+   return 1;
+   }
+   flags |= TAG_FLAG_PRE_OPTIMIZED;
 }

 query = notmuch_query_create (notmuch, query_string);
@@ -140,7 +143,7 @@ tag_query (void *ctx, notmuch_database_t *notmuch, const 
char *query_string,
 notmuch_messages_valid (messages) && ! interrupted;
 notmuch_messages_move_to_next (messages)) {
message = notmuch_messages_get (messages);
-   tag_op_list_apply (message, tag_ops, flags | TAG_FLAG_PRE_OPTIMIZED);
+   tag_op_list_apply (message, tag_ops, flags);
notmuch_message_destroy (message);
 }

@@ -157,8 +160,9 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
 notmuch_config_t *config;
 notmuch_database_t *notmuch;
 struct sigaction action;
-tag_op_flag_t synchronize_flags = TAG_FLAG_NONE;
+tag_op_flag_t flags = TAG_FLAG_NONE;
 notmuch_bool_t batch = FALSE;
+notmuch_bool_t remove_all = FALSE;
 FILE *input = stdin;
 char *input_file_name = NULL;
 int i, opt_index;
@@ -174,6 +178,7 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
 notmuch_opt_desc_t options[] = {
{ NOTMUCH_OPT_BOOLEAN, , "batch", 0, 0 },
{ NOTMUCH_OPT_STRING, _file_name, "input", 'i', 0 },
+   { NOTMUCH_OPT_BOOLEAN, _all, "remove-all", 0, 0 },
{ 0, 0, 0, 0, 0 }
 };

@@ -230,7 +235,7 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
}
}

-   if (tag_op_list_size (tag_ops) == 0) {
+   if (tag_op_list_size (tag_ops) == 0 && !remove_all) {
fprintf (stderr, "Error: 'notmuch tag' requires at least one tag to 
add or remove.\n");
return 1;
}
@@ -252,7 +257,10 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
return 1;

 if (notmuch_config_get_maildir_synchronize_flags (config))
-   synchronize_flags = TAG_FLAG_MAILDIR_SYNC;
+   flags |= TAG_FLAG_MAILDIR_SYNC;
+
+if (remove_all)
+   flags |= TAG_FLAG_REMOVE_ALL;

 if (batch) {

@@ -280,14 +288,14 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
continue;

if (ret < 0 || tag_query (ctx, notmuch, query_string,
- tag_ops, synchronize_flags))
+ tag_ops, flags))
break;
}

if (line)
free (line);
 } else
-   ret = tag_query (ctx, notmuch, query_string, tag_ops, 
synchronize_flags);
+   ret = tag_query (ctx, notmuch, query_string, tag_ops, flags);

 notmuch_database_destroy (notmuch);

-- 
1.7.10.4



[RFC PATCH] cli: add --remove-all option to notmuch tag

2012-12-03 Thread Jani Nikula
Add --remove-all option to notmuch tag to remove all tags matching
query before applying the tag changes. This allows removal and
unconditional setting of the tags of a message:

$ notmuch tag --remove-all id:f...@example.com
$ notmuch tag --remove-all +foo +bar id:f...@example.com

without having to resort to the complicated (and still quoting broken):

$ notmuch tag $(notmuch search --output=tags '*' | sed 's/^/-/') 
id:f...@example.com
$ notmuch tag $(notmuch search --output=tags '*' | sed 's/^/-/') +foo +bar 
id:f...@example.com

---

It's completely untested...

This is on top of David's batch tagging branch new-tagging at
git://pivot.cs.unb.ca/notmuch.git

If there's interest, I'll spin a new version with tests and man page
changes after David's stuff has been merged.
---
 notmuch-tag.c |   32 
 1 file changed, 20 insertions(+), 12 deletions(-)

diff --git a/notmuch-tag.c b/notmuch-tag.c
index e4fca67..67624cc 100644
--- a/notmuch-tag.c
+++ b/notmuch-tag.c
@@ -119,12 +119,15 @@ tag_query (void *ctx, notmuch_database_t *notmuch, const 
char *query_string,
 notmuch_messages_t *messages;
 notmuch_message_t *message;
 
-/* Optimize the query so it excludes messages that already have
- * the specified set of tags. */
-query_string = _optimize_tag_query (ctx, query_string, tag_ops);
-if (query_string == NULL) {
-   fprintf (stderr, Out of memory.\n);
-   return 1;
+if (! (flags  TAG_FLAG_REMOVE_ALL)) {
+   /* Optimize the query so it excludes messages that already
+* have the specified set of tags. */
+   query_string = _optimize_tag_query (ctx, query_string, tag_ops);
+   if (query_string == NULL) {
+   fprintf (stderr, Out of memory.\n);
+   return 1;
+   }
+   flags |= TAG_FLAG_PRE_OPTIMIZED;
 }
 
 query = notmuch_query_create (notmuch, query_string);
@@ -140,7 +143,7 @@ tag_query (void *ctx, notmuch_database_t *notmuch, const 
char *query_string,
 notmuch_messages_valid (messages)  ! interrupted;
 notmuch_messages_move_to_next (messages)) {
message = notmuch_messages_get (messages);
-   tag_op_list_apply (message, tag_ops, flags | TAG_FLAG_PRE_OPTIMIZED);
+   tag_op_list_apply (message, tag_ops, flags);
notmuch_message_destroy (message);
 }
 
@@ -157,8 +160,9 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
 notmuch_config_t *config;
 notmuch_database_t *notmuch;
 struct sigaction action;
-tag_op_flag_t synchronize_flags = TAG_FLAG_NONE;
+tag_op_flag_t flags = TAG_FLAG_NONE;
 notmuch_bool_t batch = FALSE;
+notmuch_bool_t remove_all = FALSE;
 FILE *input = stdin;
 char *input_file_name = NULL;
 int i, opt_index;
@@ -174,6 +178,7 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
 notmuch_opt_desc_t options[] = {
{ NOTMUCH_OPT_BOOLEAN, batch, batch, 0, 0 },
{ NOTMUCH_OPT_STRING, input_file_name, input, 'i', 0 },
+   { NOTMUCH_OPT_BOOLEAN, remove_all, remove-all, 0, 0 },
{ 0, 0, 0, 0, 0 }
 };
 
@@ -230,7 +235,7 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
}
}
 
-   if (tag_op_list_size (tag_ops) == 0) {
+   if (tag_op_list_size (tag_ops) == 0  !remove_all) {
fprintf (stderr, Error: 'notmuch tag' requires at least one tag to 
add or remove.\n);
return 1;
}
@@ -252,7 +257,10 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
return 1;
 
 if (notmuch_config_get_maildir_synchronize_flags (config))
-   synchronize_flags = TAG_FLAG_MAILDIR_SYNC;
+   flags |= TAG_FLAG_MAILDIR_SYNC;
+
+if (remove_all)
+   flags |= TAG_FLAG_REMOVE_ALL;
 
 if (batch) {
 
@@ -280,14 +288,14 @@ notmuch_tag_command (void *ctx, int argc, char *argv[])
continue;
 
if (ret  0 || tag_query (ctx, notmuch, query_string,
- tag_ops, synchronize_flags))
+ tag_ops, flags))
break;
}
 
if (line)
free (line);
 } else
-   ret = tag_query (ctx, notmuch, query_string, tag_ops, 
synchronize_flags);
+   ret = tag_query (ctx, notmuch, query_string, tag_ops, flags);
 
 notmuch_database_destroy (notmuch);
 
-- 
1.7.10.4

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