Re: [PATCH] emacs: wash: make word-wrap bound message width
[notmuch-archives.git] / 66 / 5f3129d38f7b66cf294944101d9d3e5984dadc
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 6055B431FBC\r
6         for <notmuch@notmuchmail.org>; Tue,  4 Nov 2014 16:26:40 -0800 (PST)\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 Vnjyyros3Y62 for <notmuch@notmuchmail.org>;\r
16         Tue,  4 Nov 2014 16:26:35 -0800 (PST)\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 3379D431FC0\r
19         for <notmuch@notmuchmail.org>; Tue,  4 Nov 2014 16:26:22 -0800 (PST)\r
20 Received: from localhost (unknown [192.168.200.7])\r
21         by max.feld.cvut.cz (Postfix) with ESMTP id 9E5E35CD1A8\r
22         for <notmuch@notmuchmail.org>; Wed,  5 Nov 2014 01:26:21 +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 h9udu-_Ic597 for <notmuch@notmuchmail.org>;\r
27         Wed,  5 Nov 2014 01:26:17 +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 C6F6F5CD1AF\r
30         for <notmuch@notmuchmail.org>; Wed,  5 Nov 2014 01:26:14 +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 1XloQJ-0005DN-1d; Wed, 05 Nov 2014 01:26:07 +0100\r
34 From: Michal Sojka <sojkam1@fel.cvut.cz>\r
35 To: notmuch@notmuchmail.org\r
36 Subject: [PATCH v3 10/10] cli: address: Add --filter-by option to configure\r
37         address filtering\r
38 Date: Wed,  5 Nov 2014 01:25:59 +0100\r
39 Message-Id: <1415147159-19946-11-git-send-email-sojkam1@fel.cvut.cz>\r
40 X-Mailer: git-send-email 2.1.1\r
41 In-Reply-To: <1415147159-19946-1-git-send-email-sojkam1@fel.cvut.cz>\r
42 References: <1415147159-19946-1-git-send-email-sojkam1@fel.cvut.cz>\r
43 X-BeenThere: notmuch@notmuchmail.org\r
44 X-Mailman-Version: 2.1.13\r
45 Precedence: list\r
46 List-Id: "Use and development of the notmuch mail system."\r
47         <notmuch.notmuchmail.org>\r
48 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
49         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
50 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
51 List-Post: <mailto:notmuch@notmuchmail.org>\r
52 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
53 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
54         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
55 X-List-Received-Date: Wed, 05 Nov 2014 00:26:40 -0000\r
56 \r
57 This option allows to configure the criterion for duplicate address\r
58 filtering. Without this option, all unique combinations of name and\r
59 address parts are printed. This option allows to filter the output\r
60 more, for example to only contain unique address parts.\r
61 ---\r
62  completion/notmuch-completion.bash |  6 +++-\r
63  completion/notmuch-completion.zsh  |  1 +\r
64  doc/man1/notmuch-address.rst       | 36 ++++++++++++++++++-\r
65  notmuch-search.c                   | 51 ++++++++++++++++++++++++--\r
66  test/T097-address-filter-by.sh     | 73 ++++++++++++++++++++++++++++++++++++++\r
67  5 files changed, 162 insertions(+), 5 deletions(-)\r
68  create mode 100755 test/T097-address-filter-by.sh\r
69 \r
70 diff --git a/completion/notmuch-completion.bash b/completion/notmuch-completion.bash\r
71 index db152f3..2cb1586 100644\r
72 --- a/completion/notmuch-completion.bash\r
73 +++ b/completion/notmuch-completion.bash\r
74 @@ -310,7 +310,7 @@ _notmuch_search()\r
75      ! $split &&\r
76      case "${cur}" in\r
77         -*)\r
78 -           local options="--format= --output= --sort= --offset= --limit= --exclude= --duplicate="\r
79 +           local options="--format= --output= --sort= --offset= --limit= --exclude= --duplicate= --filter-by="\r
80             compopt -o nospace\r
81             COMPREPLY=( $(compgen -W "$options" -- ${cur}) )\r
82             ;;\r
83 @@ -343,6 +343,10 @@ _notmuch_address()\r
84             COMPREPLY=( $( compgen -W "true false flag all" -- "${cur}" ) )\r
85             return\r
86             ;;\r
87 +       --filter-by)\r
88 +           COMPREPLY=( $( compgen -W "nameaddr name addr addrfold nameaddrfold" -- "${cur}" ) )\r
89 +           return\r
90 +           ;;\r
91      esac\r
92  \r
93      ! $split &&\r
94 diff --git a/completion/notmuch-completion.zsh b/completion/notmuch-completion.zsh\r
95 index 8968562..3758f1a 100644\r
96 --- a/completion/notmuch-completion.zsh\r
97 +++ b/completion/notmuch-completion.zsh\r
98 @@ -62,6 +62,7 @@ _notmuch_address()\r
99    _arguments -s : \\r
100      '--sort=[sort results]:sorting:((newest-first\:"reverse chronological order" oldest-first\:"chronological order"))' \\r
101      '--output=[select what to output]:output:((sender recipients count))'\r
102 +    '--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
103  }\r
104  \r
105  _notmuch()\r
106 diff --git a/doc/man1/notmuch-address.rst b/doc/man1/notmuch-address.rst\r
107 index 359616e..00582c3 100644\r
108 --- a/doc/man1/notmuch-address.rst\r
109 +++ b/doc/man1/notmuch-address.rst\r
110 @@ -11,7 +11,8 @@ DESCRIPTION\r
111  ===========\r
112  \r
113  Search for messages matching the given search terms, and display the\r
114 -addresses from them. Duplicate addresses are filtered out.\r
115 +addresses from them. Duplicate addresses are filtered out. Filtering\r
116 +can be configured with the --filter-by option.\r
117  \r
118  See **notmuch-search-terms(7)** for details of the supported syntax for\r
119  <search-terms>.\r
120 @@ -77,6 +78,39 @@ Supported options for **address** include\r
121          **false** allows excluded messages to match search terms and\r
122          appear in displayed results.\r
123  \r
124 +    ``--filter-by=``\ (**nameaddr**\ \|\ **name** \|\ **addr**\ \|\ **addrfold**\ \|\ **nameaddrfold**\)\r
125 +\r
126 +       Controls how to filter out duplicate addresses. The filtering\r
127 +       algorithm receives a sequence of email addresses and outputs\r
128 +       the same sequence without the addresses that are considered a\r
129 +       duplicate of a previously output address. What is considered a\r
130 +       duplicate depends on how the two addresses are compared:\r
131 +\r
132 +       **nameaddr** means that both name and address parts are\r
133 +       compared in case-sensitive manner. Therefore, all same looking\r
134 +       addresses strings are considered duplicate. This is the\r
135 +       default.\r
136 +\r
137 +       **name** means that only the name part is compared (in\r
138 +       case-sensitive manner). For example, the addresses "John Doe\r
139 +       <me@example.com>" and "John Doe <john@doe.name>" will be\r
140 +       considered duplicate.\r
141 +\r
142 +       **addr** means that only the address part is compared (in\r
143 +       case-sensitive manner). For example, the addresses "John Doe\r
144 +       <john@example.com>" and "Dr. John Doe <john@example.com>" will\r
145 +       be considered duplicate.\r
146 +\r
147 +       **addrfold** is like **addr**, but comparison is done in\r
148 +       canse-insensitive manner. For example, the addresses "John Doe\r
149 +       <john@example.com>" and "Dr. John Doe <JOHN@EXAMPLE.COM>" will\r
150 +       be considered duplicate.\r
151 +\r
152 +       **nameaddrfold** is like **nameaddr**, but address comparison\r
153 +       is done in canse-insensitive manner. For example, the\r
154 +       addresses "John Doe <john@example.com>" and "John Doe\r
155 +       <JOHN@EXAMPLE.COM>" will be considered duplicate.\r
156 +\r
157  EXIT STATUS\r
158  ===========\r
159  \r
160 diff --git a/notmuch-search.c b/notmuch-search.c\r
161 index 5036d8e..246ec0a 100644\r
162 --- a/notmuch-search.c\r
163 +++ b/notmuch-search.c\r
164 @@ -43,6 +43,14 @@ typedef enum {\r
165      NOTMUCH_FORMAT_SEXP\r
166  } format_sel_t;\r
167  \r
168 +typedef enum {\r
169 +    FILTER_BY_NAMEADDR = 0,\r
170 +    FILTER_BY_NAME,\r
171 +    FILTER_BY_ADDR,\r
172 +    FILTER_BY_ADDRFOLD,\r
173 +    FILTER_BY_NAMEADDRFOLD,\r
174 +} filter_by_t;\r
175 +\r
176  typedef struct {\r
177      notmuch_database_t *notmuch;\r
178      format_sel_t format_sel;\r
179 @@ -55,6 +63,7 @@ typedef struct {\r
180      int limit;\r
181      int dupe;\r
182      GHashTable *addresses;\r
183 +    filter_by_t filter_by;\r
184  } search_context_t;\r
185  \r
186  typedef struct {\r
187 @@ -243,16 +252,44 @@ do_search_threads (search_context_t *ctx)\r
188      return 0;\r
189  }\r
190  \r
191 -/* Returns TRUE iff name and addr is duplicate. If not, stores the\r
192 - * name/addr pair in order to detect subsequent duplicates. */\r
193 +/* Returns TRUE iff name and/or addr is considered duplicate. If not,\r
194 + * stores the name/addr pair in order to detect subsequent\r
195 + * duplicates. */\r
196  static notmuch_bool_t\r
197  is_duplicate (const search_context_t *ctx, const char *name, const char *addr)\r
198  {\r
199      notmuch_bool_t duplicate;\r
200      char *key;\r
201 +    gchar *addrfold = NULL;\r
202      mailbox_t *mailbox;\r
203  \r
204 -    key = talloc_asprintf (ctx->format, "%s <%s>", name, addr);\r
205 +    if (ctx->filter_by == FILTER_BY_ADDRFOLD ||\r
206 +       ctx->filter_by == FILTER_BY_NAMEADDRFOLD)\r
207 +       addrfold = g_utf8_casefold (addr, -1);\r
208 +\r
209 +    switch (ctx->filter_by) {\r
210 +    case FILTER_BY_NAMEADDR:\r
211 +       key = talloc_asprintf (ctx->format, "%s <%s>", name, addr);\r
212 +       break;\r
213 +    case FILTER_BY_NAMEADDRFOLD:\r
214 +       key = talloc_asprintf (ctx->format, "%s <%s>", name, addrfold);\r
215 +       break;\r
216 +    case FILTER_BY_NAME:\r
217 +       key = talloc_strdup (ctx->format, name); /* !name results in !key */\r
218 +       break;\r
219 +    case FILTER_BY_ADDR:\r
220 +       key = talloc_strdup (ctx->format, addr);\r
221 +       break;\r
222 +    case FILTER_BY_ADDRFOLD:\r
223 +       key = talloc_strdup (ctx->format, addrfold);\r
224 +       break;\r
225 +    default:\r
226 +       INTERNAL_ERROR("invalid --filter-by flags");\r
227 +    }\r
228 +\r
229 +    if (addrfold)\r
230 +       g_free (addrfold);\r
231 +\r
232      if (! key)\r
233         return FALSE;\r
234  \r
235 @@ -727,10 +764,18 @@ notmuch_address_command (notmuch_config_t *config, int argc, char *argv[])\r
236           (notmuch_keyword_t []){ { "true", NOTMUCH_EXCLUDE_TRUE },\r
237                                   { "false", NOTMUCH_EXCLUDE_FALSE },\r
238                                   { 0, 0 } } },\r
239 +       { NOTMUCH_OPT_KEYWORD, &ctx->filter_by, "filter-by", 'b',\r
240 +         (notmuch_keyword_t []){ { "nameaddr", FILTER_BY_NAMEADDR },\r
241 +                                 { "name", FILTER_BY_NAME },\r
242 +                                 { "addr", FILTER_BY_ADDR },\r
243 +                                 { "addrfold", FILTER_BY_ADDRFOLD },\r
244 +                                 { "nameaddrfold", FILTER_BY_NAMEADDRFOLD },\r
245 +                                 { 0, 0 } } },\r
246         { NOTMUCH_OPT_INHERIT, &common_options, NULL, 0, 0 },\r
247         { 0, 0, 0, 0, 0 }\r
248      };\r
249  \r
250 +    ctx->filter_by = FILTER_BY_NAMEADDR,\r
251      opt_index = parse_arguments (argc, argv, options, 1);\r
252      if (opt_index < 0)\r
253         return EXIT_FAILURE;\r
254 diff --git a/test/T097-address-filter-by.sh b/test/T097-address-filter-by.sh\r
255 new file mode 100755\r
256 index 0000000..544d8e8\r
257 --- /dev/null\r
258 +++ b/test/T097-address-filter-by.sh\r
259 @@ -0,0 +1,73 @@\r
260 +#!/usr/bin/env bash\r
261 +test_description='duplicite address filtering in "notmuch address"'\r
262 +. ./test-lib.sh\r
263 +\r
264 +add_message '[to]="John Doe <foo@example.com>, John Doe <bar@example.com>"'\r
265 +add_message '[to]="\"Doe, John\" <foo@example.com>"' '[cc]="John Doe <Bar@Example.COM>"'\r
266 +add_message '[to]="\"Doe, John\" <foo@example.com>"' '[bcc]="John Doe <Bar@Example.COM>"'\r
267 +\r
268 +test_begin_subtest "--output=recipients"\r
269 +notmuch address --output=recipients "*" >OUTPUT\r
270 +cat <<EOF >EXPECTED\r
271 +John Doe <foo@example.com>\r
272 +John Doe <bar@example.com>\r
273 +"Doe, John" <foo@example.com>\r
274 +John Doe <Bar@Example.COM>\r
275 +EOF\r
276 +test_expect_equal_file OUTPUT EXPECTED\r
277 +\r
278 +test_begin_subtest "--output=recipients --filter-by=nameaddr"\r
279 +notmuch address --output=recipients --filter-by=nameaddr "*" >OUTPUT\r
280 +# The same as above\r
281 +cat <<EOF >EXPECTED\r
282 +John Doe <foo@example.com>\r
283 +John Doe <bar@example.com>\r
284 +"Doe, John" <foo@example.com>\r
285 +John Doe <Bar@Example.COM>\r
286 +EOF\r
287 +test_expect_equal_file OUTPUT EXPECTED\r
288 +\r
289 +test_begin_subtest "--output=recipients --filter-by=name"\r
290 +notmuch address --output=recipients --filter-by=name "*" >OUTPUT\r
291 +cat <<EOF >EXPECTED\r
292 +John Doe <foo@example.com>\r
293 +"Doe, John" <foo@example.com>\r
294 +EOF\r
295 +test_expect_equal_file OUTPUT EXPECTED\r
296 +\r
297 +test_begin_subtest "--output=recipients --filter-by=addr"\r
298 +notmuch address --output=recipients --filter-by=addr "*" >OUTPUT\r
299 +cat <<EOF >EXPECTED\r
300 +John Doe <foo@example.com>\r
301 +John Doe <bar@example.com>\r
302 +John Doe <Bar@Example.COM>\r
303 +EOF\r
304 +test_expect_equal_file OUTPUT EXPECTED\r
305 +\r
306 +test_begin_subtest "--output=recipients --filter-by=addrfold"\r
307 +notmuch address --output=recipients --filter-by=addrfold "*" >OUTPUT\r
308 +cat <<EOF >EXPECTED\r
309 +John Doe <foo@example.com>\r
310 +John Doe <bar@example.com>\r
311 +EOF\r
312 +test_expect_equal_file OUTPUT EXPECTED\r
313 +\r
314 +test_begin_subtest "--output=recipients --filter-by=nameaddrfold"\r
315 +notmuch address --output=recipients --filter-by=nameaddrfold "*" >OUTPUT\r
316 +cat <<EOF >EXPECTED\r
317 +John Doe <foo@example.com>\r
318 +John Doe <bar@example.com>\r
319 +"Doe, John" <foo@example.com>\r
320 +EOF\r
321 +test_expect_equal_file OUTPUT EXPECTED\r
322 +\r
323 +test_begin_subtest "--output=recipients --filter-by=nameaddrfold --output=count"\r
324 +notmuch address --output=recipients --filter-by=nameaddrfold --output=count "*" | sort -n >OUTPUT\r
325 +cat <<EOF >EXPECTED\r
326 +1      John Doe <foo@example.com>\r
327 +2      "Doe, John" <foo@example.com>\r
328 +3      John Doe <bar@example.com>\r
329 +EOF\r
330 +test_expect_equal_file OUTPUT EXPECTED\r
331 +\r
332 +test_done\r
333 -- \r
334 2.1.1\r
335 \r