[PATCH] cli: add --output=filesandtags to notmuch search

classic Classic list List threaded Threaded
2 messages Options
Vincent Breitmoser Vincent Breitmoser
Reply | Threaded
Open this post in threaded view
|

[PATCH] cli: add --output=filesandtags to notmuch search

This commit adds a filesandtags output format, which outputs the
filenames of all matching messages together with their tags. Files and
tags are separated by newlines or null-bytes for --format=text or text0
respectively, so that filenames and tags are on alternating lines. The
json and sexp output formats are a list of maps, with a "filename" and
"tags" key each.

The rationale for this output parameter is to have a way of searching
messages with notmuch in a scenario where display of message info is
taken care of by another application based on filenames (e.g. mblaze),
but that also want to make use of related tags.  This use case isn't
covered with any other notmuch search output format, and very cumbersome
with notmuch show.

It's possible to cover this workflow with a trivial python script.
However in a quick test, a query that returned 40 messages was about
three times slower for me with a python script with a hot cache, and
even worse with a cold cache.
---
 NEWS                        |   7 ++
 doc/man1/notmuch-search.rst |  10 ++-
 notmuch-search.c            |  58 +++++++++++-
 test/T090-search-output.sh  | 171 ++++++++++++++++++++++++++++++++++++
 4 files changed, 241 insertions(+), 5 deletions(-)

diff --git a/NEWS b/NEWS
index 240d594b..18e8a08d 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,10 @@
+Command Line Interface
+----------------------
+
+Add the --output=filesandtags option to `notmuch search`
+
+  This option outputs both the filenames and tags of relevant messages.
+
 Notmuch 0.27 (2018-06-13)
 =========================
 
diff --git a/doc/man1/notmuch-search.rst b/doc/man1/notmuch-search.rst
index 654c5f2c..96593096 100644
--- a/doc/man1/notmuch-search.rst
+++ b/doc/man1/notmuch-search.rst
@@ -35,7 +35,7 @@ Supported options for **search** include
     intended for programs that invoke **notmuch(1)** internally. If
     omitted, the latest supported version will be used.
 
-``--output=(summary|threads|messages|files|tags)``
+``--output=(summary|threads|messages|files|tags|filesandtags)``
     **summary**
         Output a summary of each thread with any message matching the
         search terms. The summary includes the thread ID, date, the
@@ -71,6 +71,14 @@ Supported options for **search** include
         in other directories that are included in the output, although
         these files alone would not match the search.
 
+    **filesandtags**
+        Output the filenames of all messages matching the search terms, together
+        with their corresponding tags. Filenames and tags are output as lines in
+        an alternating fashion so that filenames are on odd lines and their tags
+        on the following even line (``--format=text``), as a JSON arrray of
+        objects (``--format=text``), or as an S-Expression list
+        (``--format=sexp``).
+
     **tags**
         Output all tags that appear on any message matching the search
         terms, either one per line (``--format=text``), separated by null
diff --git a/notmuch-search.c b/notmuch-search.c
index 8f467db4..65167afa 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -29,12 +29,13 @@ typedef enum {
     OUTPUT_MESSAGES = 1 << 2,
     OUTPUT_FILES = 1 << 3,
     OUTPUT_TAGS = 1 << 4,
+    OUTPUT_FILESANDTAGS = 1 << 5,
 
     /* Address command */
-    OUTPUT_SENDER = 1 << 5,
-    OUTPUT_RECIPIENTS = 1 << 6,
-    OUTPUT_COUNT = 1 << 7,
-    OUTPUT_ADDRESS = 1 << 8,
+    OUTPUT_SENDER = 1 << 6,
+    OUTPUT_RECIPIENTS = 1 << 7,
+    OUTPUT_COUNT = 1 << 8,
+    OUTPUT_ADDRESS = 1 << 9,
 } output_t;
 
 typedef enum {
@@ -537,6 +538,7 @@ do_search_messages (search_context_t *ctx)
     notmuch_message_t *message;
     notmuch_messages_t *messages;
     notmuch_filenames_t *filenames;
+    notmuch_tags_t *tags;
     sprinter_t *format = ctx->format;
     int i;
     notmuch_status_t status;
@@ -583,6 +585,52 @@ do_search_messages (search_context_t *ctx)
     }
     
     notmuch_filenames_destroy( filenames );
+ } else if (ctx->output == OUTPUT_FILESANDTAGS) {
+    int j;
+    filenames = notmuch_message_get_filenames (message);
+
+    for (j = 1;
+    notmuch_filenames_valid (filenames);
+    notmuch_filenames_move_to_next (filenames), j++)
+    {
+
+ if (ctx->dupe < 0 || ctx->dupe == j) {
+    format->begin_map (format);
+    format->map_key (format, "filename");
+
+    format->string (format, notmuch_filenames_get (filenames));
+    if (format->is_text_printer) {
+ format->separator (format);
+    }
+
+    format->map_key (format, "tags");
+    format->begin_list (format);
+
+    bool first_tag = true;
+    for (tags = notmuch_message_get_tags (message);
+    notmuch_tags_valid (tags);
+    notmuch_tags_move_to_next (tags))
+    {
+ const char *tag = notmuch_tags_get (tags);
+ if (format->is_text_printer) {
+    if (first_tag)
+ first_tag = false;
+    else
+ fputc (' ', stdout);
+    fputs (tag, stdout);
+ } else { /* Structured Output */
+    format->string (format, tag);
+ }
+    }
+    notmuch_tags_destroy( tags );
+    format->end (format);
+
+    format->end (format);
+    format->separator (format);
+ }
+
+    }
+    notmuch_filenames_destroy( filenames );
 
  } else if (ctx->output == OUTPUT_MESSAGES) {
             /* special case 1 for speed */
@@ -816,6 +864,7 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
   { "threads", OUTPUT_THREADS },
   { "messages", OUTPUT_MESSAGES },
   { "files", OUTPUT_FILES },
+  { "filesandtags", OUTPUT_FILESANDTAGS },
   { "tags", OUTPUT_TAGS },
   { 0, 0 } } },
         { .opt_keyword = &ctx->exclude, .name = "exclude", .keywords =
@@ -856,6 +905,7 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
  break;
     case OUTPUT_MESSAGES:
     case OUTPUT_FILES:
+    case OUTPUT_FILESANDTAGS:
  ret = do_search_messages (ctx);
  break;
     case OUTPUT_TAGS:
diff --git a/test/T090-search-output.sh b/test/T090-search-output.sh
index bf28d220..e294a5cc 100755
--- a/test/T090-search-output.sh
+++ b/test/T090-search-output.sh
@@ -276,6 +276,177 @@ MAIL_DIR/new/04:2,
 EOF
 test_expect_equal_file EXPECTED OUTPUT
 
+test_begin_subtest "--output=filesandtags"
+notmuch search --output=filesandtags '*' | notmuch_search_files_sanitize >OUTPUT
+cat <<EOF >EXPECTED
+MAIL_DIR/cur/52:2,
+inbox unread
+MAIL_DIR/cur/53:2,
+inbox unread
+MAIL_DIR/cur/50:2,
+inbox unread
+MAIL_DIR/cur/49:2,
+inbox unread
+MAIL_DIR/cur/48:2,
+inbox unread
+MAIL_DIR/cur/47:2,
+inbox unread
+MAIL_DIR/cur/46:2,
+inbox unread
+MAIL_DIR/cur/45:2,
+inbox unread
+MAIL_DIR/cur/44:2,
+inbox unread
+MAIL_DIR/cur/43:2,
+inbox unread
+MAIL_DIR/cur/42:2,
+inbox unread
+MAIL_DIR/cur/41:2,
+inbox unread
+MAIL_DIR/cur/40:2,
+inbox unread
+MAIL_DIR/cur/39:2,
+inbox unread
+MAIL_DIR/cur/38:2,
+inbox unread
+MAIL_DIR/cur/37:2,
+inbox unread
+MAIL_DIR/cur/36:2,
+inbox unread
+MAIL_DIR/cur/35:2,
+inbox unread
+MAIL_DIR/cur/34:2,
+inbox unread
+MAIL_DIR/cur/33:2,
+inbox unread
+MAIL_DIR/cur/32:2,
+inbox unread
+MAIL_DIR/cur/31:2,
+inbox unread
+MAIL_DIR/cur/30:2,
+inbox unread
+MAIL_DIR/cur/29:2,
+inbox unread
+MAIL_DIR/bar/baz/new/28:2,
+inbox unread
+MAIL_DIR/bar/baz/new/27:2,
+inbox unread
+MAIL_DIR/bar/baz/cur/26:2,
+inbox unread
+MAIL_DIR/bar/baz/cur/25:2,
+inbox unread
+MAIL_DIR/bar/baz/24:2,
+attachment inbox signed unread
+MAIL_DIR/bar/baz/23:2,
+attachment inbox signed unread
+MAIL_DIR/bar/new/22:2,
+inbox signed unread
+MAIL_DIR/bar/new/21:2,
+attachment inbox unread
+MAIL_DIR/bar/cur/19:2,
+inbox unread
+MAIL_DIR/cur/51:2,
+inbox unread
+MAIL_DIR/bar/18:2,
+inbox unread
+MAIL_DIR/bar/cur/20:2,
+inbox signed unread
+MAIL_DIR/bar/17:2,
+inbox unread
+MAIL_DIR/foo/baz/new/16:2,
+inbox unread
+MAIL_DIR/foo/baz/new/15:2,
+inbox unread
+MAIL_DIR/foo/baz/cur/14:2,
+inbox unread
+MAIL_DIR/foo/baz/cur/13:2,
+inbox unread
+MAIL_DIR/foo/baz/12:2,
+inbox unread
+MAIL_DIR/foo/baz/11:2,
+inbox unread
+MAIL_DIR/foo/new/10:2,
+inbox unread
+MAIL_DIR/foo/new/09:2,
+inbox unread
+MAIL_DIR/foo/cur/08:2,
+inbox signed unread
+MAIL_DIR/foo/06:2,
+inbox unread
+MAIL_DIR/bar/baz/05:2,
+attachment inbox unread
+MAIL_DIR/new/04:2,
+inbox signed unread
+MAIL_DIR/foo/new/03:2,
+inbox signed unread
+MAIL_DIR/foo/cur/07:2,
+inbox unread
+MAIL_DIR/02:2,
+inbox unread
+MAIL_DIR/01:2,
+inbox unread
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
+test_begin_subtest "--output=filesandtags --format=json"
+notmuch search --output=filesandtags --format=json '*' | notmuch_search_files_sanitize >OUTPUT
+cat <<EOF >EXPECTED
+[{"filename": "MAIL_DIR/cur/52:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/53:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/50:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/49:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/48:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/47:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/46:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/45:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/44:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/43:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/42:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/41:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/40:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/39:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/38:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/37:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/36:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/35:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/34:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/33:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/32:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/31:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/30:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/29:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/bar/baz/new/28:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/bar/baz/new/27:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/bar/baz/cur/26:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/bar/baz/cur/25:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/bar/baz/24:2,", "tags": ["attachment", "inbox", "signed", "unread"]},
+{"filename": "MAIL_DIR/bar/baz/23:2,", "tags": ["attachment", "inbox", "signed", "unread"]},
+{"filename": "MAIL_DIR/bar/new/22:2,", "tags": ["inbox", "signed", "unread"]},
+{"filename": "MAIL_DIR/bar/new/21:2,", "tags": ["attachment", "inbox", "unread"]},
+{"filename": "MAIL_DIR/bar/cur/19:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/cur/51:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/bar/18:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/bar/cur/20:2,", "tags": ["inbox", "signed", "unread"]},
+{"filename": "MAIL_DIR/bar/17:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/foo/baz/new/16:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/foo/baz/new/15:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/foo/baz/cur/14:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/foo/baz/cur/13:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/foo/baz/12:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/foo/baz/11:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/foo/new/10:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/foo/new/09:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/foo/cur/08:2,", "tags": ["inbox", "signed", "unread"]},
+{"filename": "MAIL_DIR/foo/06:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/bar/baz/05:2,", "tags": ["attachment", "inbox", "unread"]},
+{"filename": "MAIL_DIR/new/04:2,", "tags": ["inbox", "signed", "unread"]},
+{"filename": "MAIL_DIR/foo/new/03:2,", "tags": ["inbox", "signed", "unread"]},
+{"filename": "MAIL_DIR/foo/cur/07:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/02:2,", "tags": ["inbox", "unread"]},
+{"filename": "MAIL_DIR/01:2,", "tags": ["inbox", "unread"]}]
+EOF
+test_expect_equal_file EXPECTED OUTPUT
+
 dup1=$(notmuch search --output=files id:[hidden email] | head -n 1 | sed -e "s,$MAIL_DIR,MAIL_DIR,")
 dup2=$(notmuch search --output=files id:[hidden email] | tail -n 1 | sed -e "s,$MAIL_DIR,MAIL_DIR,")
 
--
2.18.0

_______________________________________________
notmuch mailing list
[hidden email]
https://notmuchmail.org/mailman/listinfo/notmuch
Tomi Ollila-2 Tomi Ollila-2
Reply | Threaded
Open this post in threaded view
|

Re: [PATCH] cli: add --output=filesandtags to notmuch search

On Mon, Sep 03 2018, Vincent Breitmoser wrote:

> This commit adds a filesandtags output format, which outputs the
> filenames of all matching messages together with their tags. Files and
> tags are separated by newlines or null-bytes for --format=text or text0
> respectively, so that filenames and tags are on alternating lines. The

Do we already write output to multiple lines per message entry in text
output. If not this makes a change to this consistency. But we may
have spaces in filenames (Sent Items or such idiotism >;D) and in tags.
The only thing that comes mind as a separator would be // if filenams
and tags are put into same line, but that looks somewhat odd...


> json and sexp output formats are a list of maps, with a "filename" and
> "tags" key each.
>
> The rationale for this output parameter is to have a way of searching
> messages with notmuch in a scenario where display of message info is
> taken care of by another application based on filenames (e.g. mblaze),
> but that also want to make use of related tags.  This use case isn't
> covered with any other notmuch search output format, and very cumbersome
> with notmuch show.
>
> It's possible to cover this workflow with a trivial python script.
> However in a quick test, a query that returned 40 messages was about
> three times slower for me with a python script with a hot cache, and
> even worse with a cold cache.
> ---
>  NEWS                        |   7 ++
>  doc/man1/notmuch-search.rst |  10 ++-
>  notmuch-search.c            |  58 +++++++++++-
>  test/T090-search-output.sh  | 171 ++++++++++++++++++++++++++++++++++++
>  4 files changed, 241 insertions(+), 5 deletions(-)
>
> diff --git a/NEWS b/NEWS
> index 240d594b..18e8a08d 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -1,3 +1,10 @@
> +Command Line Interface
> +----------------------
> +
> +Add the --output=filesandtags option to `notmuch search`
> +
> +  This option outputs both the filenames and tags of relevant messages.
> +
>  Notmuch 0.27 (2018-06-13)
>  =========================
>  
> diff --git a/doc/man1/notmuch-search.rst b/doc/man1/notmuch-search.rst
> index 654c5f2c..96593096 100644
> --- a/doc/man1/notmuch-search.rst
> +++ b/doc/man1/notmuch-search.rst
> @@ -35,7 +35,7 @@ Supported options for **search** include
>      intended for programs that invoke **notmuch(1)** internally. If
>      omitted, the latest supported version will be used.
>  
> -``--output=(summary|threads|messages|files|tags)``
> +``--output=(summary|threads|messages|files|tags|filesandtags)``
>      **summary**
>          Output a summary of each thread with any message matching the
>          search terms. The summary includes the thread ID, date, the
> @@ -71,6 +71,14 @@ Supported options for **search** include
>          in other directories that are included in the output, although
>          these files alone would not match the search.
>  
> +    **filesandtags**
> +        Output the filenames of all messages matching the search terms, together
> +        with their corresponding tags. Filenames and tags are output as lines in
> +        an alternating fashion so that filenames are on odd lines and their tags
> +        on the following even line (``--format=text``), as a JSON arrray of
> +        objects (``--format=text``), or as an S-Expression list
> +        (``--format=sexp``).
> +
>      **tags**
>          Output all tags that appear on any message matching the search
>          terms, either one per line (``--format=text``), separated by null
> diff --git a/notmuch-search.c b/notmuch-search.c
> index 8f467db4..65167afa 100644
> --- a/notmuch-search.c
> +++ b/notmuch-search.c
> @@ -29,12 +29,13 @@ typedef enum {
>      OUTPUT_MESSAGES = 1 << 2,
>      OUTPUT_FILES = 1 << 3,
>      OUTPUT_TAGS = 1 << 4,
> +    OUTPUT_FILESANDTAGS = 1 << 5,
>  
>      /* Address command */
> -    OUTPUT_SENDER = 1 << 5,
> -    OUTPUT_RECIPIENTS = 1 << 6,
> -    OUTPUT_COUNT = 1 << 7,
> -    OUTPUT_ADDRESS = 1 << 8,
> +    OUTPUT_SENDER = 1 << 6,
> +    OUTPUT_RECIPIENTS = 1 << 7,
> +    OUTPUT_COUNT = 1 << 8,
> +    OUTPUT_ADDRESS = 1 << 9,
>  } output_t;
>  
>  typedef enum {
> @@ -537,6 +538,7 @@ do_search_messages (search_context_t *ctx)
>      notmuch_message_t *message;
>      notmuch_messages_t *messages;
>      notmuch_filenames_t *filenames;
> +    notmuch_tags_t *tags;
>      sprinter_t *format = ctx->format;
>      int i;
>      notmuch_status_t status;
> @@ -583,6 +585,52 @@ do_search_messages (search_context_t *ctx)
>      }
>      
>      notmuch_filenames_destroy( filenames );
> + } else if (ctx->output == OUTPUT_FILESANDTAGS) {
> +    int j;
> +    filenames = notmuch_message_get_filenames (message);
> +
> +    for (j = 1;
> +    notmuch_filenames_valid (filenames);
> +    notmuch_filenames_move_to_next (filenames), j++)
> +    {
> +
> + if (ctx->dupe < 0 || ctx->dupe == j) {
> +    format->begin_map (format);
> +    format->map_key (format, "filename");
> +
> +    format->string (format, notmuch_filenames_get (filenames));
> +    if (format->is_text_printer) {
> + format->separator (format);
> +    }
> +
> +    format->map_key (format, "tags");
> +    format->begin_list (format);
> +
> +    bool first_tag = true;
> +    for (tags = notmuch_message_get_tags (message);
> +    notmuch_tags_valid (tags);
> +    notmuch_tags_move_to_next (tags))
> +    {
> + const char *tag = notmuch_tags_get (tags);
> + if (format->is_text_printer) {
> +    if (first_tag)
> + first_tag = false;
> +    else
> + fputc (' ', stdout);
> +    fputs (tag, stdout);
> + } else { /* Structured Output */
> +    format->string (format, tag);
> + }
> +    }
> +    notmuch_tags_destroy( tags );
> +    format->end (format);
> +
> +    format->end (format);
> +    format->separator (format);
> + }
> +
> +    }
> +    notmuch_filenames_destroy( filenames );
>  
>   } else if (ctx->output == OUTPUT_MESSAGES) {
>              /* special case 1 for speed */
> @@ -816,6 +864,7 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
>    { "threads", OUTPUT_THREADS },
>    { "messages", OUTPUT_MESSAGES },
>    { "files", OUTPUT_FILES },
> +  { "filesandtags", OUTPUT_FILESANDTAGS },
>    { "tags", OUTPUT_TAGS },
>    { 0, 0 } } },
>          { .opt_keyword = &ctx->exclude, .name = "exclude", .keywords =
> @@ -856,6 +905,7 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])
>   break;
>      case OUTPUT_MESSAGES:
>      case OUTPUT_FILES:
> +    case OUTPUT_FILESANDTAGS:
>   ret = do_search_messages (ctx);
>   break;
>      case OUTPUT_TAGS:
> diff --git a/test/T090-search-output.sh b/test/T090-search-output.sh
> index bf28d220..e294a5cc 100755
> --- a/test/T090-search-output.sh
> +++ b/test/T090-search-output.sh
> @@ -276,6 +276,177 @@ MAIL_DIR/new/04:2,
>  EOF
>  test_expect_equal_file EXPECTED OUTPUT
>  
> +test_begin_subtest "--output=filesandtags"
> +notmuch search --output=filesandtags '*' | notmuch_search_files_sanitize >OUTPUT
> +cat <<EOF >EXPECTED
> +MAIL_DIR/cur/52:2,
> +inbox unread
> +MAIL_DIR/cur/53:2,
> +inbox unread
> +MAIL_DIR/cur/50:2,
> +inbox unread
> +MAIL_DIR/cur/49:2,
> +inbox unread
> +MAIL_DIR/cur/48:2,
> +inbox unread
> +MAIL_DIR/cur/47:2,
> +inbox unread
> +MAIL_DIR/cur/46:2,
> +inbox unread
> +MAIL_DIR/cur/45:2,
> +inbox unread
> +MAIL_DIR/cur/44:2,
> +inbox unread
> +MAIL_DIR/cur/43:2,
> +inbox unread
> +MAIL_DIR/cur/42:2,
> +inbox unread
> +MAIL_DIR/cur/41:2,
> +inbox unread
> +MAIL_DIR/cur/40:2,
> +inbox unread
> +MAIL_DIR/cur/39:2,
> +inbox unread
> +MAIL_DIR/cur/38:2,
> +inbox unread
> +MAIL_DIR/cur/37:2,
> +inbox unread
> +MAIL_DIR/cur/36:2,
> +inbox unread
> +MAIL_DIR/cur/35:2,
> +inbox unread
> +MAIL_DIR/cur/34:2,
> +inbox unread
> +MAIL_DIR/cur/33:2,
> +inbox unread
> +MAIL_DIR/cur/32:2,
> +inbox unread
> +MAIL_DIR/cur/31:2,
> +inbox unread
> +MAIL_DIR/cur/30:2,
> +inbox unread
> +MAIL_DIR/cur/29:2,
> +inbox unread
> +MAIL_DIR/bar/baz/new/28:2,
> +inbox unread
> +MAIL_DIR/bar/baz/new/27:2,
> +inbox unread
> +MAIL_DIR/bar/baz/cur/26:2,
> +inbox unread
> +MAIL_DIR/bar/baz/cur/25:2,
> +inbox unread
> +MAIL_DIR/bar/baz/24:2,
> +attachment inbox signed unread
> +MAIL_DIR/bar/baz/23:2,
> +attachment inbox signed unread
> +MAIL_DIR/bar/new/22:2,
> +inbox signed unread
> +MAIL_DIR/bar/new/21:2,
> +attachment inbox unread
> +MAIL_DIR/bar/cur/19:2,
> +inbox unread
> +MAIL_DIR/cur/51:2,
> +inbox unread
> +MAIL_DIR/bar/18:2,
> +inbox unread
> +MAIL_DIR/bar/cur/20:2,
> +inbox signed unread
> +MAIL_DIR/bar/17:2,
> +inbox unread
> +MAIL_DIR/foo/baz/new/16:2,
> +inbox unread
> +MAIL_DIR/foo/baz/new/15:2,
> +inbox unread
> +MAIL_DIR/foo/baz/cur/14:2,
> +inbox unread
> +MAIL_DIR/foo/baz/cur/13:2,
> +inbox unread
> +MAIL_DIR/foo/baz/12:2,
> +inbox unread
> +MAIL_DIR/foo/baz/11:2,
> +inbox unread
> +MAIL_DIR/foo/new/10:2,
> +inbox unread
> +MAIL_DIR/foo/new/09:2,
> +inbox unread
> +MAIL_DIR/foo/cur/08:2,
> +inbox signed unread
> +MAIL_DIR/foo/06:2,
> +inbox unread
> +MAIL_DIR/bar/baz/05:2,
> +attachment inbox unread
> +MAIL_DIR/new/04:2,
> +inbox signed unread
> +MAIL_DIR/foo/new/03:2,
> +inbox signed unread
> +MAIL_DIR/foo/cur/07:2,
> +inbox unread
> +MAIL_DIR/02:2,
> +inbox unread
> +MAIL_DIR/01:2,
> +inbox unread
> +EOF
> +test_expect_equal_file EXPECTED OUTPUT
> +
> +test_begin_subtest "--output=filesandtags --format=json"
> +notmuch search --output=filesandtags --format=json '*' | notmuch_search_files_sanitize >OUTPUT
> +cat <<EOF >EXPECTED
> +[{"filename": "MAIL_DIR/cur/52:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/53:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/50:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/49:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/48:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/47:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/46:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/45:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/44:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/43:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/42:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/41:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/40:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/39:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/38:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/37:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/36:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/35:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/34:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/33:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/32:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/31:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/30:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/29:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/bar/baz/new/28:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/bar/baz/new/27:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/bar/baz/cur/26:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/bar/baz/cur/25:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/bar/baz/24:2,", "tags": ["attachment", "inbox", "signed", "unread"]},
> +{"filename": "MAIL_DIR/bar/baz/23:2,", "tags": ["attachment", "inbox", "signed", "unread"]},
> +{"filename": "MAIL_DIR/bar/new/22:2,", "tags": ["inbox", "signed", "unread"]},
> +{"filename": "MAIL_DIR/bar/new/21:2,", "tags": ["attachment", "inbox", "unread"]},
> +{"filename": "MAIL_DIR/bar/cur/19:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/cur/51:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/bar/18:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/bar/cur/20:2,", "tags": ["inbox", "signed", "unread"]},
> +{"filename": "MAIL_DIR/bar/17:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/foo/baz/new/16:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/foo/baz/new/15:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/foo/baz/cur/14:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/foo/baz/cur/13:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/foo/baz/12:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/foo/baz/11:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/foo/new/10:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/foo/new/09:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/foo/cur/08:2,", "tags": ["inbox", "signed", "unread"]},
> +{"filename": "MAIL_DIR/foo/06:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/bar/baz/05:2,", "tags": ["attachment", "inbox", "unread"]},
> +{"filename": "MAIL_DIR/new/04:2,", "tags": ["inbox", "signed", "unread"]},
> +{"filename": "MAIL_DIR/foo/new/03:2,", "tags": ["inbox", "signed", "unread"]},
> +{"filename": "MAIL_DIR/foo/cur/07:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/02:2,", "tags": ["inbox", "unread"]},
> +{"filename": "MAIL_DIR/01:2,", "tags": ["inbox", "unread"]}]
> +EOF
> +test_expect_equal_file EXPECTED OUTPUT
> +
>  dup1=$(notmuch search --output=files id:[hidden email] | head -n 1 | sed -e "s,$MAIL_DIR,MAIL_DIR,")
>  dup2=$(notmuch search --output=files id:[hidden email] | tail -n 1 | sed -e "s,$MAIL_DIR,MAIL_DIR,")
>  
> --
> 2.18.0
>
> _______________________________________________
> notmuch mailing list
> [hidden email]
> https://notmuchmail.org/mailman/listinfo/notmuch
_______________________________________________
notmuch mailing list
[hidden email]
https://notmuchmail.org/mailman/listinfo/notmuch