Re: [PATCH] emacs: wash: make word-wrap bound message width
[notmuch-archives.git] / 66 / 2bae04c774f059bd142c6c31658092b809518a
1 Return-Path: <sojkam1@fel.cvut.cz>\r
2 X-Original-To: notmuch@notmuchmail.org\r
3 Delivered-To: notmuch@notmuchmail.org\r
4 Received: from localhost (localhost [127.0.0.1])\r
5         by olra.theworths.org (Postfix) with ESMTP id 0FC08429E25\r
6         for <notmuch@notmuchmail.org>; Mon, 27 Oct 2014 07:51:27 -0700 (PDT)\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org\r
8 X-Spam-Flag: NO\r
9 X-Spam-Score: -2.3\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-2.3 tagged_above=-999 required=5\r
12         tests=[RCVD_IN_DNSWL_MED=-2.3] autolearn=disabled\r
13 Received: from olra.theworths.org ([127.0.0.1])\r
14         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
15         with ESMTP id 4iANC6I8aJqI for <notmuch@notmuchmail.org>;\r
16         Mon, 27 Oct 2014 07:51:19 -0700 (PDT)\r
17 Received: from max.feld.cvut.cz (max.feld.cvut.cz [147.32.192.36])\r
18         by olra.theworths.org (Postfix) with ESMTP id 8DB89431FDB\r
19         for <notmuch@notmuchmail.org>; Mon, 27 Oct 2014 07:51:14 -0700 (PDT)\r
20 Received: from localhost (unknown [192.168.200.7])\r
21         by max.feld.cvut.cz (Postfix) with ESMTP id 0683A5CCF9D\r
22         for <notmuch@notmuchmail.org>; Mon, 27 Oct 2014 15:51:12 +0100 (CET)\r
23 X-Virus-Scanned: IMAP STYX AMAVIS\r
24 Received: from max.feld.cvut.cz ([192.168.200.1])\r
25         by localhost (styx.feld.cvut.cz [192.168.200.7]) (amavisd-new,\r
26         port 10044) with ESMTP id 6W_eysLIWzpe for <notmuch@notmuchmail.org>;\r
27         Mon, 27 Oct 2014 15:51:08 +0100 (CET)\r
28 Received: from imap.feld.cvut.cz (imap.feld.cvut.cz [147.32.192.34])\r
29         by max.feld.cvut.cz (Postfix) with ESMTP id 9A4A35CCF92\r
30         for <notmuch@notmuchmail.org>; Mon, 27 Oct 2014 15:51:07 +0100 (CET)\r
31 Received: from wsh by steelpick.2x.cz with local (Exim 4.84)\r
32         (envelope-from <sojkam1@fel.cvut.cz>)\r
33         id 1XildT-0000os-JS; Mon, 27 Oct 2014 15:51:07 +0100\r
34 From: Michal Sojka <sojkam1@fel.cvut.cz>\r
35 To: notmuch@notmuchmail.org\r
36 Subject: [PATCH v4 5/6] cli: search: Add configurable way to filter out\r
37         duplicate addresses\r
38 Date: Mon, 27 Oct 2014 15:50:54 +0100\r
39 Message-Id: <1414421455-3037-6-git-send-email-sojkam1@fel.cvut.cz>\r
40 X-Mailer: git-send-email 2.1.1\r
41 In-Reply-To: <1414421455-3037-1-git-send-email-sojkam1@fel.cvut.cz>\r
42 References: <1414421455-3037-1-git-send-email-sojkam1@fel.cvut.cz>\r
43 MIME-Version: 1.0\r
44 Content-Type: text/plain; charset=UTF-8\r
45 Content-Transfer-Encoding: 8bit\r
46 X-BeenThere: notmuch@notmuchmail.org\r
47 X-Mailman-Version: 2.1.13\r
48 Precedence: list\r
49 List-Id: "Use and development of the notmuch mail system."\r
50         <notmuch.notmuchmail.org>\r
51 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
52         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
53 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
54 List-Post: <mailto:notmuch@notmuchmail.org>\r
55 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
56 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
57         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
58 X-List-Received-Date: Mon, 27 Oct 2014 14:51:27 -0000\r
59 \r
60 This adds an algorithm to filter out duplicate addresses from address\r
61 outputs (sender, receivers). The algorithm can be configured with\r
62 --filter-by command line option.\r
63 \r
64 The code here is an extended version of a patch from Jani Nikula.\r
65 ---\r
66  completion/notmuch-completion.bash |  6 ++-\r
67  completion/notmuch-completion.zsh  |  3 +-\r
68  doc/man1/notmuch-search.rst        | 38 +++++++++++++++\r
69  notmuch-search.c                   | 98 +++++++++++++++++++++++++++++++++++---\r
70  test/T090-search-output.sh         | 87 +++++++++++++++++++++++++++++++++\r
71  test/T095-search-filter-by.sh      | 64 +++++++++++++++++++++++++\r
72  6 files changed, 288 insertions(+), 8 deletions(-)\r
73  create mode 100755 test/T095-search-filter-by.sh\r
74 \r
75 diff --git a/completion/notmuch-completion.bash b/completion/notmuch-completion.bash\r
76 index cfbd389..6b6d43a 100644\r
77 --- a/completion/notmuch-completion.bash\r
78 +++ b/completion/notmuch-completion.bash\r
79 @@ -305,12 +305,16 @@ _notmuch_search()\r
80             COMPREPLY=( $( compgen -W "true false flag all" -- "${cur}" ) )\r
81             return\r
82             ;;\r
83 +       --filter-by)\r
84 +           COMPREPLY=( $( compgen -W "nameaddr name addr addrfold nameaddrfold" -- "${cur}" ) )\r
85 +           return\r
86 +           ;;\r
87      esac\r
88  \r
89      ! $split &&\r
90      case "${cur}" in\r
91         -*)\r
92 -           local options="--format= --output= --sort= --offset= --limit= --exclude= --duplicate="\r
93 +           local options="--format= --output= --sort= --offset= --limit= --exclude= --duplicate= --filter-by="\r
94             compopt -o nospace\r
95             COMPREPLY=( $(compgen -W "$options" -- ${cur}) )\r
96             ;;\r
97 diff --git a/completion/notmuch-completion.zsh b/completion/notmuch-completion.zsh\r
98 index 3e52a00..3e535df 100644\r
99 --- a/completion/notmuch-completion.zsh\r
100 +++ b/completion/notmuch-completion.zsh\r
101 @@ -53,7 +53,8 @@ _notmuch_search()\r
102      '--max-threads=[display only the first x threads from the search results]:number of threads to show: ' \\r
103      '--first=[omit the first x threads from the search results]:number of threads to omit: ' \\r
104      '--sort=[sort results]:sorting:((newest-first\:"reverse chronological order" oldest-first\:"chronological order"))' \\r
105 -    '--output=[select what to output]:output:((summary threads messages files tags sender recipients))'\r
106 +    '--output=[select what to output]:output:((summary threads messages files tags sender recipients))' \\r
107 +    '--filter-by=[filter out duplicate addresses]:filter-by:((nameaddr\:"both name and address part" name\:"name part" addr\:"address part" addrfold\:"case-insensitive address part" nameaddrfold\:"name and case-insensitive address part"))'\r
108  }\r
109  \r
110  _notmuch()\r
111 diff --git a/doc/man1/notmuch-search.rst b/doc/man1/notmuch-search.rst\r
112 index b6607c9..84af2da 100644\r
113 --- a/doc/man1/notmuch-search.rst\r
114 +++ b/doc/man1/notmuch-search.rst\r
115 @@ -85,6 +85,9 @@ Supported options for **search** include\r
116              (--format=text0), as a JSON array (--format=json), or as\r
117              an S-Expression list (--format=sexp).\r
118  \r
119 +            Duplicate addresses are filtered out. Filtering can be\r
120 +            configured with the --filter-by option.\r
121 +\r
122             Note: Searching for **sender** should be much faster than\r
123             searching for **recipients**, because sender addresses are\r
124             cached directly in the database whereas other addresses\r
125 @@ -151,6 +154,41 @@ Supported options for **search** include\r
126          prefix. The prefix matches messages based on filenames. This\r
127          option filters filenames of the matching messages.\r
128  \r
129 +    ``--filter-by=``\ (**nameaddr**\ \|\ **name** \|\ **addr**\ \|\ **addrfold**\ \|\ **nameaddrfold**\)\r
130 +\r
131 +       Can be used with ``--output=sender`` or\r
132 +       ``--output=recipients`` to filter out duplicate addresses. The\r
133 +       filtering algorithm receives a sequence of email addresses and\r
134 +       outputs the same sequence without the addresses that are\r
135 +       considered a duplicate of a previously output address. What is\r
136 +       considered a duplicate depends on how the two addresses are\r
137 +       compared and this can be controlled with the follwing flags:\r
138 +\r
139 +       **nameaddr** means that both name and address parts are\r
140 +       compared in case-sensitive manner. Therefore, all same looking\r
141 +       addresses strings are considered duplicate. This is the\r
142 +       default.\r
143 +\r
144 +       **name** means that only the name part is compared (in\r
145 +       case-sensitive manner). For example, the addresses "John Doe\r
146 +       <me@example.com>" and "John Doe <john@doe.name>" will be\r
147 +       considered duplicate.\r
148 +\r
149 +       **addr** means that only the address part is compared (in\r
150 +       case-sensitive manner). For example, the addresses "John Doe\r
151 +       <john@example.com>" and "Dr. John Doe <john@example.com>" will\r
152 +       be considered duplicate.\r
153 +\r
154 +       **addrfold** is like **addr**, but comparison is done in\r
155 +       canse-insensitive manner. For example, the addresses "John Doe\r
156 +       <john@example.com>" and "Dr. John Doe <JOHN@EXAMPLE.COM>" will\r
157 +       be considered duplicate.\r
158 +\r
159 +       **nameaddrfold** is like **nameaddr**, but address comparison\r
160 +       is done in canse-insensitive manner. For example, the\r
161 +       addresses "John Doe <john@example.com>" and "John Doe\r
162 +       <JOHN@EXAMPLE.COM>" will be considered duplicate.\r
163 +\r
164  EXIT STATUS\r
165  ===========\r
166  \r
167 diff --git a/notmuch-search.c b/notmuch-search.c\r
168 index ce3bfb2..47aa979 100644\r
169 --- a/notmuch-search.c\r
170 +++ b/notmuch-search.c\r
171 @@ -34,6 +34,14 @@ typedef enum {\r
172  \r
173  #define OUTPUT_ADDRESS_FLAGS (OUTPUT_SENDER | OUTPUT_RECIPIENTS)\r
174  \r
175 +typedef enum {\r
176 +    FILTER_BY_NAMEADDR = 0,\r
177 +    FILTER_BY_NAME,\r
178 +    FILTER_BY_ADDR,\r
179 +    FILTER_BY_ADDRFOLD,\r
180 +    FILTER_BY_NAMEADDRFOLD,\r
181 +} filter_by_t;\r
182 +\r
183  typedef struct {\r
184      sprinter_t *format;\r
185      notmuch_query_t *query;\r
186 @@ -42,6 +50,7 @@ typedef struct {\r
187      int offset;\r
188      int limit;\r
189      int dupe;\r
190 +    filter_by_t filter_by;\r
191  } search_options_t;\r
192  \r
193  typedef struct {\r
194 @@ -229,6 +238,52 @@ do_search_threads (search_options_t *opt)\r
195      return 0;\r
196  }\r
197  \r
198 +/* Returns TRUE iff name and/or addr is considered duplicite. */\r
199 +static notmuch_bool_t\r
200 +check_duplicite (const search_options_t *opt, GHashTable *addrs, const char *name, const char *addr)\r
201 +{\r
202 +    notmuch_bool_t duplicite;\r
203 +    char *key;\r
204 +\r
205 +    if (opt->filter_by == FILTER_BY_ADDRFOLD ||\r
206 +       opt->filter_by == FILTER_BY_NAMEADDRFOLD) {\r
207 +       gchar *folded = g_utf8_casefold (addr, -1);\r
208 +       addr = talloc_strdup (opt->format, folded);\r
209 +       g_free (folded);\r
210 +    }\r
211 +    switch (opt->filter_by) {\r
212 +    case FILTER_BY_NAMEADDR:\r
213 +    case FILTER_BY_NAMEADDRFOLD:\r
214 +       key = talloc_asprintf (opt->format, "%s <%s>", name, addr);\r
215 +       break;\r
216 +    case FILTER_BY_NAME:\r
217 +       key = talloc_strdup (opt->format, name); /* !name results in !key */\r
218 +       break;\r
219 +    case FILTER_BY_ADDR:\r
220 +    case FILTER_BY_ADDRFOLD:\r
221 +       key = talloc_strdup (opt->format, addr);\r
222 +       break;\r
223 +    default:\r
224 +       INTERNAL_ERROR("invalid --filter-by flags");\r
225 +    }\r
226 +\r
227 +    if (opt->filter_by == FILTER_BY_ADDRFOLD ||\r
228 +       opt->filter_by == FILTER_BY_NAMEADDRFOLD)\r
229 +       talloc_free ((char*)addr);\r
230 +\r
231 +    if (! key)\r
232 +       return FALSE;\r
233 +\r
234 +    duplicite = g_hash_table_lookup_extended (addrs, key, NULL, NULL);\r
235 +\r
236 +    if (! duplicite)\r
237 +       g_hash_table_insert (addrs, key, NULL);\r
238 +    else\r
239 +       talloc_free (key);\r
240 +\r
241 +    return duplicite;\r
242 +}\r
243 +\r
244  static void\r
245  print_mailbox (const search_options_t *opt, const mailbox_t *mailbox)\r
246  {\r
247 @@ -263,7 +318,8 @@ print_mailbox (const search_options_t *opt, const mailbox_t *mailbox)\r
248  }\r
249  \r
250  static void\r
251 -process_address_list (const search_options_t *opt, InternetAddressList *list)\r
252 +process_address_list (const search_options_t *opt, GHashTable *addrs,\r
253 +                     InternetAddressList *list)\r
254  {\r
255      InternetAddress *address;\r
256      int i;\r
257 @@ -279,7 +335,7 @@ process_address_list (const search_options_t *opt, InternetAddressList *list)\r
258             if (group_list == NULL)\r
259                 continue;\r
260  \r
261 -           process_address_list (opt, group_list);\r
262 +           process_address_list (opt, addrs, group_list);\r
263         } else {\r
264             InternetAddressMailbox *mailbox = INTERNET_ADDRESS_MAILBOX (address);\r
265             mailbox_t mbx = {\r
266 @@ -287,13 +343,16 @@ process_address_list (const search_options_t *opt, InternetAddressList *list)\r
267                 .addr = internet_address_mailbox_get_addr (mailbox),\r
268             };\r
269  \r
270 +           if (check_duplicite (opt, addrs, mbx.name, mbx.addr))\r
271 +               continue;\r
272 +\r
273             print_mailbox (opt, &mbx);\r
274         }\r
275      }\r
276  }\r
277  \r
278  static void\r
279 -process_address_header (const search_options_t *opt, const char *value)\r
280 +process_address_header (const search_options_t *opt, GHashTable *addrs, const char *value)\r
281  {\r
282      InternetAddressList *list;\r
283  \r
284 @@ -304,7 +363,13 @@ process_address_header (const search_options_t *opt, const char *value)\r
285      if (list == NULL)\r
286         return;\r
287  \r
288 -    process_address_list (opt, list);\r
289 +    process_address_list (opt, addrs, list);\r
290 +}\r
291 +\r
292 +static void\r
293 +_my_talloc_free_for_g_hash (void *ptr)\r
294 +{\r
295 +    talloc_free (ptr);\r
296  }\r
297  \r
298  static int\r
299 @@ -314,8 +379,13 @@ do_search_messages (search_options_t *opt)\r
300      notmuch_messages_t *messages;\r
301      notmuch_filenames_t *filenames;\r
302      sprinter_t *format = opt->format;\r
303 +    GHashTable *addresses = NULL;\r
304      int i;\r
305  \r
306 +    if (opt->output & OUTPUT_ADDRESS_FLAGS)\r
307 +       addresses = g_hash_table_new_full (g_str_hash, g_str_equal,\r
308 +                                          _my_talloc_free_for_g_hash, NULL);\r
309 +\r
310      if (opt->offset < 0) {\r
311         opt->offset += notmuch_query_count_messages (opt->query);\r
312         if (opt->offset < 0)\r
313 @@ -363,7 +433,7 @@ do_search_messages (search_options_t *opt)\r
314                 const char *addrs;\r
315  \r
316                 addrs = notmuch_message_get_header (message, "from");\r
317 -               process_address_header (opt, addrs);\r
318 +               process_address_header (opt, addresses, addrs);\r
319             }\r
320  \r
321             if (opt->output & OUTPUT_RECIPIENTS) {\r
322 @@ -373,7 +443,7 @@ do_search_messages (search_options_t *opt)\r
323  \r
324                 for (j = 0; j < ARRAY_SIZE (hdrs); j++) {\r
325                     addrs = notmuch_message_get_header (message, hdrs[j]);\r
326 -                   process_address_header (opt, addrs);\r
327 +                   process_address_header (opt, addresses, addrs);\r
328                 }\r
329             }\r
330         }\r
331 @@ -381,6 +451,9 @@ do_search_messages (search_options_t *opt)\r
332         notmuch_message_destroy (message);\r
333      }\r
334  \r
335 +    if (addresses)\r
336 +       g_hash_table_unref (addresses);\r
337 +\r
338      notmuch_messages_destroy (messages);\r
339  \r
340      format->end (format);\r
341 @@ -447,6 +520,7 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])\r
342         .offset = 0,\r
343         .limit = -1, /* unlimited */\r
344         .dupe = -1,\r
345 +       .filter_by = FILTER_BY_NAMEADDR,\r
346      };\r
347      char *query_str;\r
348      int opt_index, ret;\r
349 @@ -490,6 +564,13 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])\r
350         { NOTMUCH_OPT_INT, &opt.offset, "offset", 'O', 0 },\r
351         { NOTMUCH_OPT_INT, &opt.limit, "limit", 'L', 0  },\r
352         { NOTMUCH_OPT_INT, &opt.dupe, "duplicate", 'D', 0  },\r
353 +       { NOTMUCH_OPT_KEYWORD, &opt.filter_by, "filter-by", 'b',\r
354 +         (notmuch_keyword_t []){ { "nameaddr", FILTER_BY_NAMEADDR },\r
355 +                                 { "name", FILTER_BY_NAME },\r
356 +                                 { "addr", FILTER_BY_ADDR },\r
357 +                                 { "addrfold", FILTER_BY_ADDRFOLD },\r
358 +                                 { "nameaddrfold", FILTER_BY_NAMEADDRFOLD },\r
359 +                                 { 0, 0 } } },\r
360         { 0, 0, 0, 0, 0 }\r
361      };\r
362  \r
363 @@ -500,6 +581,11 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])\r
364      if (! opt.output)\r
365         opt.output = OUTPUT_SUMMARY;\r
366  \r
367 +    if (opt.filter_by && !(opt.output & OUTPUT_ADDRESS_FLAGS)) {\r
368 +       fprintf (stderr, "Error: --filter-by can only be used with address output.\n");\r
369 +       return EXIT_FAILURE;\r
370 +    }\r
371 +\r
372      switch (format_sel) {\r
373      case NOTMUCH_FORMAT_TEXT:\r
374         opt.format = sprinter_text_create (config, stdout);\r
375 diff --git a/test/T090-search-output.sh b/test/T090-search-output.sh\r
376 index 947d572..841a721 100755\r
377 --- a/test/T090-search-output.sh\r
378 +++ b/test/T090-search-output.sh\r
379 @@ -387,6 +387,93 @@ cat <<EOF >EXPECTED\r
380  EOF\r
381  test_expect_equal_file OUTPUT EXPECTED\r
382  \r
383 +test_begin_subtest "--output=sender"\r
384 +notmuch search --output=sender '*' >OUTPUT\r
385 +cat <<EOF >EXPECTED\r
386 +François Boulogne <boulogne.f@gmail.com>\r
387 +Olivier Berger <olivier.berger@it-sudparis.eu>\r
388 +Chris Wilson <chris@chris-wilson.co.uk>\r
389 +Carl Worth <cworth@cworth.org>\r
390 +Alexander Botero-Lowry <alex.boterolowry@gmail.com>\r
391 +Keith Packard <keithp@keithp.com>\r
392 +Jjgod Jiang <gzjjgod@gmail.com>\r
393 +Rolland Santimano <rollandsantimano@yahoo.com>\r
394 +Jan Janak <jan@ryngle.com>\r
395 +Stewart Smith <stewart@flamingspork.com>\r
396 +Lars Kellogg-Stedman <lars@seas.harvard.edu>\r
397 +Alex Botero-Lowry <alex.boterolowry@gmail.com>\r
398 +Ingmar Vanhassel <ingmar@exherbo.org>\r
399 +Aron Griffis <agriffis@n01se.net>\r
400 +Adrian Perez de Castro <aperez@igalia.com>\r
401 +Israel Herraiz <isra@herraiz.org>\r
402 +Mikhail Gusarov <dottedmag@dottedmag.net>\r
403 +EOF\r
404 +test_expect_equal_file OUTPUT EXPECTED\r
405 +\r
406 +test_begin_subtest "--output=sender --format=json"\r
407 +notmuch search --output=sender --format=json '*' >OUTPUT\r
408 +cat <<EOF >EXPECTED\r
409 +[{"name": "François Boulogne", "address": "boulogne.f@gmail.com"},\r
410 +{"name": "Olivier Berger", "address": "olivier.berger@it-sudparis.eu"},\r
411 +{"name": "Chris Wilson", "address": "chris@chris-wilson.co.uk"},\r
412 +{"name": "Carl Worth", "address": "cworth@cworth.org"},\r
413 +{"name": "Alexander Botero-Lowry", "address": "alex.boterolowry@gmail.com"},\r
414 +{"name": "Keith Packard", "address": "keithp@keithp.com"},\r
415 +{"name": "Jjgod Jiang", "address": "gzjjgod@gmail.com"},\r
416 +{"name": "Rolland Santimano", "address": "rollandsantimano@yahoo.com"},\r
417 +{"name": "Jan Janak", "address": "jan@ryngle.com"},\r
418 +{"name": "Stewart Smith", "address": "stewart@flamingspork.com"},\r
419 +{"name": "Lars Kellogg-Stedman", "address": "lars@seas.harvard.edu"},\r
420 +{"name": "Alex Botero-Lowry", "address": "alex.boterolowry@gmail.com"},\r
421 +{"name": "Ingmar Vanhassel", "address": "ingmar@exherbo.org"},\r
422 +{"name": "Aron Griffis", "address": "agriffis@n01se.net"},\r
423 +{"name": "Adrian Perez de Castro", "address": "aperez@igalia.com"},\r
424 +{"name": "Israel Herraiz", "address": "isra@herraiz.org"},\r
425 +{"name": "Mikhail Gusarov", "address": "dottedmag@dottedmag.net"}]\r
426 +EOF\r
427 +test_expect_equal_file OUTPUT EXPECTED\r
428 +\r
429 +test_begin_subtest "--output=recipients"\r
430 +notmuch search --output=recipients '*' >OUTPUT\r
431 +cat <<EOF >EXPECTED\r
432 +Allan McRae <allan@archlinux.org>\r
433 +Discussion about the Arch User Repository (AUR) <aur-general@archlinux.org>\r
434 +olivier.berger@it-sudparis.eu\r
435 +notmuch@notmuchmail.org\r
436 +notmuch <notmuch@notmuchmail.org>\r
437 +Keith Packard <keithp@keithp.com>\r
438 +Mikhail Gusarov <dottedmag@dottedmag.net>\r
439 +EOF\r
440 +test_expect_equal_file OUTPUT EXPECTED\r
441 +\r
442 +test_begin_subtest "--output=sender --output=recipients"\r
443 +notmuch search --output=sender --output=recipients '*' >OUTPUT\r
444 +cat <<EOF >EXPECTED\r
445 +François Boulogne <boulogne.f@gmail.com>\r
446 +Allan McRae <allan@archlinux.org>\r
447 +Discussion about the Arch User Repository (AUR) <aur-general@archlinux.org>\r
448 +Olivier Berger <olivier.berger@it-sudparis.eu>\r
449 +olivier.berger@it-sudparis.eu\r
450 +Chris Wilson <chris@chris-wilson.co.uk>\r
451 +notmuch@notmuchmail.org\r
452 +Carl Worth <cworth@cworth.org>\r
453 +Alexander Botero-Lowry <alex.boterolowry@gmail.com>\r
454 +Keith Packard <keithp@keithp.com>\r
455 +Jjgod Jiang <gzjjgod@gmail.com>\r
456 +Rolland Santimano <rollandsantimano@yahoo.com>\r
457 +Jan Janak <jan@ryngle.com>\r
458 +Stewart Smith <stewart@flamingspork.com>\r
459 +Lars Kellogg-Stedman <lars@seas.harvard.edu>\r
460 +notmuch <notmuch@notmuchmail.org>\r
461 +Alex Botero-Lowry <alex.boterolowry@gmail.com>\r
462 +Ingmar Vanhassel <ingmar@exherbo.org>\r
463 +Aron Griffis <agriffis@n01se.net>\r
464 +Adrian Perez de Castro <aperez@igalia.com>\r
465 +Israel Herraiz <isra@herraiz.org>\r
466 +Mikhail Gusarov <dottedmag@dottedmag.net>\r
467 +EOF\r
468 +test_expect_equal_file OUTPUT EXPECTED\r
469 +\r
470  test_begin_subtest "sanitize output for quoted-printable line-breaks in author and subject"\r
471  add_message "[subject]='two =?ISO-8859-1?Q?line=0A_subject?=\r
472         headers'"\r
473 diff --git a/test/T095-search-filter-by.sh b/test/T095-search-filter-by.sh\r
474 new file mode 100755\r
475 index 0000000..97d9a9b\r
476 --- /dev/null\r
477 +++ b/test/T095-search-filter-by.sh\r
478 @@ -0,0 +1,64 @@\r
479 +#!/usr/bin/env bash\r
480 +test_description='duplicite address filtering in "notmuch search --output=recipients"'\r
481 +. ./test-lib.sh\r
482 +\r
483 +add_message '[to]="Real Name <foo@example.com>, Real Name <bar@example.com>"'\r
484 +add_message '[to]="Nickname <foo@example.com>"' '[cc]="Real Name <Bar@Example.COM>"'\r
485 +add_message '[to]="Nickname <foo@example.com>"' '[bcc]="Real Name <Bar@Example.COM>"'\r
486 +\r
487 +test_begin_subtest "--output=recipients"\r
488 +notmuch search --output=recipients "*" >OUTPUT\r
489 +cat <<EOF >EXPECTED\r
490 +Real Name <foo@example.com>\r
491 +Real Name <bar@example.com>\r
492 +Nickname <foo@example.com>\r
493 +Real Name <Bar@Example.COM>\r
494 +EOF\r
495 +test_expect_equal_file OUTPUT EXPECTED\r
496 +\r
497 +test_begin_subtest "--output=recipients --filter-by=nameaddr"\r
498 +notmuch search --output=recipients --filter-by=nameaddr "*" >OUTPUT\r
499 +# The same as above\r
500 +cat <<EOF >EXPECTED\r
501 +Real Name <foo@example.com>\r
502 +Real Name <bar@example.com>\r
503 +Nickname <foo@example.com>\r
504 +Real Name <Bar@Example.COM>\r
505 +EOF\r
506 +test_expect_equal_file OUTPUT EXPECTED\r
507 +\r
508 +test_begin_subtest "--output=recipients --filter-by=name"\r
509 +notmuch search --output=recipients --filter-by=name "*" >OUTPUT\r
510 +cat <<EOF >EXPECTED\r
511 +Real Name <foo@example.com>\r
512 +Nickname <foo@example.com>\r
513 +EOF\r
514 +test_expect_equal_file OUTPUT EXPECTED\r
515 +\r
516 +test_begin_subtest "--output=recipients --filter-by=addr"\r
517 +notmuch search --output=recipients --filter-by=addr "*" >OUTPUT\r
518 +cat <<EOF >EXPECTED\r
519 +Real Name <foo@example.com>\r
520 +Real Name <bar@example.com>\r
521 +Real Name <Bar@Example.COM>\r
522 +EOF\r
523 +test_expect_equal_file OUTPUT EXPECTED\r
524 +\r
525 +test_begin_subtest "--output=recipients --filter-by=addrfold"\r
526 +notmuch search --output=recipients --filter-by=addrfold "*" >OUTPUT\r
527 +cat <<EOF >EXPECTED\r
528 +Real Name <foo@example.com>\r
529 +Real Name <bar@example.com>\r
530 +EOF\r
531 +test_expect_equal_file OUTPUT EXPECTED\r
532 +\r
533 +test_begin_subtest "--output=recipients --filter-by=nameaddrfold"\r
534 +notmuch search --output=recipients --filter-by=nameaddrfold "*" >OUTPUT\r
535 +cat <<EOF >EXPECTED\r
536 +Real Name <foo@example.com>\r
537 +Real Name <bar@example.com>\r
538 +Nickname <foo@example.com>\r
539 +EOF\r
540 +test_expect_equal_file OUTPUT EXPECTED\r
541 +\r
542 +test_done\r
543 -- \r
544 2.1.1\r
545 \r