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 22999431FAF
\r
6 for <notmuch@notmuchmail.org>; Sat, 1 Nov 2014 17:50:46 -0700 (PDT)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\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 rBnNLzTx8a2Y for <notmuch@notmuchmail.org>;
\r
16 Sat, 1 Nov 2014 17:50:38 -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 9AF1C429E26
\r
19 for <notmuch@notmuchmail.org>; Sat, 1 Nov 2014 17:50:16 -0700 (PDT)
\r
20 Received: from localhost (unknown [192.168.200.7])
\r
21 by max.feld.cvut.cz (Postfix) with ESMTP id A49F55CD28F
\r
22 for <notmuch@notmuchmail.org>; Sun, 2 Nov 2014 01:50:14 +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 Mto6qc0I5Mzw for <notmuch@notmuchmail.org>;
\r
27 Sun, 2 Nov 2014 01:50:11 +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 8C55B5CD28D
\r
30 for <notmuch@notmuchmail.org>; Sun, 2 Nov 2014 01:50:10 +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 1XkjMq-00085Q-KU; Sun, 02 Nov 2014 01:50:04 +0100
\r
34 From: Michal Sojka <sojkam1@fel.cvut.cz>
\r
35 To: notmuch@notmuchmail.org
\r
36 Subject: [PATCH 09/10] cli: address: Add --output=count
\r
37 Date: Sun, 2 Nov 2014 01:49:59 +0100
\r
38 Message-Id: <1414889400-30977-10-git-send-email-sojkam1@fel.cvut.cz>
\r
39 X-Mailer: git-send-email 2.1.1
\r
40 In-Reply-To: <1414889400-30977-1-git-send-email-sojkam1@fel.cvut.cz>
\r
41 References: <1414889400-30977-1-git-send-email-sojkam1@fel.cvut.cz>
\r
43 Content-Type: text/plain; charset=UTF-8
\r
44 Content-Transfer-Encoding: 8bit
\r
45 X-BeenThere: notmuch@notmuchmail.org
\r
46 X-Mailman-Version: 2.1.13
\r
48 List-Id: "Use and development of the notmuch mail system."
\r
49 <notmuch.notmuchmail.org>
\r
50 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
51 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
52 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
53 List-Post: <mailto:notmuch@notmuchmail.org>
\r
54 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
55 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
56 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
57 X-List-Received-Date: Sun, 02 Nov 2014 00:50:46 -0000
\r
59 This output prints how many times was each address encountered during
\r
62 completion/notmuch-completion.bash | 2 +-
\r
63 completion/notmuch-completion.zsh | 2 +-
\r
64 doc/man1/notmuch-address.rst | 7 ++++++
\r
65 notmuch-search.c | 49 ++++++++++++++++++++++++++++++++------
\r
66 test/T095-address.sh | 48 +++++++++++++++++++++++++++++++++++++
\r
67 5 files changed, 99 insertions(+), 9 deletions(-)
\r
69 diff --git a/completion/notmuch-completion.bash b/completion/notmuch-completion.bash
\r
70 index 94ea2d5..db152f3 100644
\r
71 --- a/completion/notmuch-completion.bash
\r
72 +++ b/completion/notmuch-completion.bash
\r
73 @@ -332,7 +332,7 @@ _notmuch_address()
\r
77 - COMPREPLY=( $( compgen -W "sender recipients" -- "${cur}" ) )
\r
78 + COMPREPLY=( $( compgen -W "sender recipients count" -- "${cur}" ) )
\r
82 diff --git a/completion/notmuch-completion.zsh b/completion/notmuch-completion.zsh
\r
83 index c606b75..8968562 100644
\r
84 --- a/completion/notmuch-completion.zsh
\r
85 +++ b/completion/notmuch-completion.zsh
\r
86 @@ -61,7 +61,7 @@ _notmuch_address()
\r
89 '--sort=[sort results]:sorting:((newest-first\:"reverse chronological order" oldest-first\:"chronological order"))' \
\r
90 - '--output=[select what to output]:output:((sender recipients))'
\r
91 + '--output=[select what to output]:output:((sender recipients count))'
\r
95 diff --git a/doc/man1/notmuch-address.rst b/doc/man1/notmuch-address.rst
\r
96 index 96512b7..18473a7 100644
\r
97 --- a/doc/man1/notmuch-address.rst
\r
98 +++ b/doc/man1/notmuch-address.rst
\r
99 @@ -48,6 +48,13 @@ Supported options for **address** include
\r
100 Output all addresses from the *To*, *Cc* and *Bcc*
\r
104 + Print the count of how many times was the address
\r
105 + encountered during search.
\r
107 + Note: With this option, addresses are printed only after
\r
108 + the whole search is finished. This may take long time.
\r
110 ``--sort=``\ (**newest-first**\ \|\ **oldest-first**)
\r
111 This option can be used to present results in either
\r
112 chronological order (**oldest-first**) or reverse chronological
\r
113 diff --git a/notmuch-search.c b/notmuch-search.c
\r
114 index c765017..b45d480 100644
\r
115 --- a/notmuch-search.c
\r
116 +++ b/notmuch-search.c
\r
117 @@ -33,6 +33,7 @@ typedef enum {
\r
118 /* Address command */
\r
119 OUTPUT_SENDER = 1 << 5,
\r
120 OUTPUT_RECIPIENTS = 1 << 6,
\r
121 + OUTPUT_COUNT = 1 << 7,
\r
125 @@ -59,6 +60,7 @@ typedef struct {
\r
132 /* Return two stable query strings that identify exactly the matched
\r
133 @@ -247,17 +249,24 @@ is_duplicate (const search_context_t *ctx, const char *name, const char *addr)
\r
135 notmuch_bool_t duplicate;
\r
137 + mailbox_t *mailbox;
\r
139 key = talloc_asprintf (ctx->format, "%s <%s>", name, addr);
\r
143 - duplicate = g_hash_table_lookup_extended (ctx->addresses, key, NULL, NULL);
\r
144 + duplicate = g_hash_table_lookup_extended (ctx->addresses, key, NULL, (gpointer)&mailbox);
\r
147 - g_hash_table_insert (ctx->addresses, key, NULL);
\r
149 + if (! duplicate) {
\r
150 + mailbox = talloc (ctx->format, mailbox_t);
\r
151 + mailbox->name = talloc_strdup (mailbox, name);
\r
152 + mailbox->addr = talloc_strdup (mailbox, addr);
\r
153 + mailbox->count = 1;
\r
154 + g_hash_table_insert (ctx->addresses, key, mailbox);
\r
156 + mailbox->count++;
\r
162 @@ -267,6 +276,7 @@ print_mailbox (const search_context_t *ctx, const mailbox_t *mailbox)
\r
164 const char *name = mailbox->name;
\r
165 const char *addr = mailbox->addr;
\r
166 + int count = mailbox->count;
\r
167 sprinter_t *format = ctx->format;
\r
168 InternetAddress *ia = internet_address_mailbox_new (name, addr);
\r
170 @@ -276,6 +286,10 @@ print_mailbox (const search_context_t *ctx, const mailbox_t *mailbox)
\r
171 name_addr = internet_address_to_string (ia, FALSE);
\r
173 if (format->is_text_printer) {
\r
175 + format->integer (format, count);
\r
176 + format->string (format, "\t");
\r
178 format->string (format, name_addr);
\r
179 format->separator (format);
\r
181 @@ -286,6 +300,10 @@ print_mailbox (const search_context_t *ctx, const mailbox_t *mailbox)
\r
182 format->string (format, addr);
\r
183 format->map_key (format, "name-addr");
\r
184 format->string (format, name_addr);
\r
186 + format->map_key (format, "count");
\r
187 + format->integer (format, count);
\r
189 format->end (format);
\r
190 format->separator (format);
\r
192 @@ -294,7 +312,7 @@ print_mailbox (const search_context_t *ctx, const mailbox_t *mailbox)
\r
193 g_free (name_addr);
\r
196 -/* Print addresses from InternetAddressList. */
\r
197 +/* Print or prepare for printing addresses from InternetAddressList. */
\r
199 process_address_list (const search_context_t *ctx,
\r
200 InternetAddressList *list)
\r
201 @@ -319,17 +337,21 @@ process_address_list (const search_context_t *ctx,
\r
203 .name = internet_address_get_name (address),
\r
204 .addr = internet_address_mailbox_get_addr (mailbox),
\r
208 if (is_duplicate (ctx, mbx.name, mbx.addr))
\r
211 + if (ctx->output & OUTPUT_COUNT)
\r
214 print_mailbox (ctx, &mbx);
\r
219 -/* Print addresses from a message header. */
\r
220 +/* Print or prepare for printing addresses from a message header. */
\r
222 process_address_header (const search_context_t *ctx, const char *value)
\r
224 @@ -353,6 +375,15 @@ _my_talloc_free_for_g_hash (void *ptr)
\r
229 +print_hash_value (unused (gpointer key), gpointer value, gpointer user_data)
\r
231 + const mailbox_t *mailbox = value;
\r
232 + search_context_t *ctx = user_data;
\r
234 + print_mailbox (ctx, mailbox);
\r
238 do_search_messages (search_context_t *ctx)
\r
240 @@ -427,6 +458,9 @@ do_search_messages (search_context_t *ctx)
\r
241 notmuch_message_destroy (message);
\r
244 + if (ctx->addresses && ctx->output & OUTPUT_COUNT)
\r
245 + g_hash_table_foreach (ctx->addresses, print_hash_value, ctx);
\r
247 notmuch_messages_destroy (messages);
\r
249 format->end (format);
\r
250 @@ -658,6 +692,7 @@ notmuch_address_command (notmuch_config_t *config, int argc, char *argv[])
\r
251 { NOTMUCH_OPT_KEYWORD_FLAGS, &ctx->output, "output", 'o',
\r
252 (notmuch_keyword_t []){ { "sender", OUTPUT_SENDER },
\r
253 { "recipients", OUTPUT_RECIPIENTS },
\r
254 + { "count", OUTPUT_COUNT },
\r
256 { NOTMUCH_OPT_INHERIT, &common_options, NULL, 0, 0 },
\r
258 @@ -675,7 +710,7 @@ notmuch_address_command (notmuch_config_t *config, int argc, char *argv[])
\r
259 return EXIT_FAILURE;
\r
261 ctx->addresses = g_hash_table_new_full (g_str_hash, g_str_equal,
\r
262 - _my_talloc_free_for_g_hash, NULL);
\r
263 + _my_talloc_free_for_g_hash, _my_talloc_free_for_g_hash);
\r
265 ret = do_search_messages (ctx);
\r
267 diff --git a/test/T095-address.sh b/test/T095-address.sh
\r
268 index 8a256d2..92e17b0 100755
\r
269 --- a/test/T095-address.sh
\r
270 +++ b/test/T095-address.sh
\r
271 @@ -96,5 +96,53 @@ notmuch address --output=sender --output=recipients '*' >OUTPUT
\r
272 # Use EXPECTED from previous subtest
\r
273 test_expect_equal_file OUTPUT EXPECTED
\r
275 +test_begin_subtest "--output=sender --output=count"
\r
276 +notmuch address --output=sender --output=count '*' | sort -n >OUTPUT
\r
277 +cat <<EOF >EXPECTED
\r
278 +1 Adrian Perez de Castro <aperez@igalia.com>
\r
279 +1 Aron Griffis <agriffis@n01se.net>
\r
280 +1 Chris Wilson <chris@chris-wilson.co.uk>
\r
281 +1 François Boulogne <boulogne.f@gmail.com>
\r
282 +1 Ingmar Vanhassel <ingmar@exherbo.org>
\r
283 +1 Israel Herraiz <isra@herraiz.org>
\r
284 +1 Olivier Berger <olivier.berger@it-sudparis.eu>
\r
285 +1 Rolland Santimano <rollandsantimano@yahoo.com>
\r
286 +2 Alex Botero-Lowry <alex.boterolowry@gmail.com>
\r
287 +2 Jjgod Jiang <gzjjgod@gmail.com>
\r
288 +3 Stewart Smith <stewart@flamingspork.com>
\r
289 +4 Alexander Botero-Lowry <alex.boterolowry@gmail.com>
\r
290 +4 Jan Janak <jan@ryngle.com>
\r
291 +5 Lars Kellogg-Stedman <lars@seas.harvard.edu>
\r
292 +5 Mikhail Gusarov <dottedmag@dottedmag.net>
\r
293 +7 Keith Packard <keithp@keithp.com>
\r
294 +12 Carl Worth <cworth@cworth.org>
\r
296 +test_expect_equal_file OUTPUT EXPECTED
\r
298 +test_begin_subtest "--output=sender --output=count --format=json"
\r
299 +# Since the iteration order of GHashTable is not specified, we
\r
300 +# preprocess and sort the results to keep the order stable here.
\r
301 +notmuch address --output=sender --output=count --format=json '*' | \
\r
302 + sed -e 's/^\[//' -e 's/]$//' -e 's/,$//' | sort >OUTPUT
\r
303 +cat <<EOF >EXPECTED
\r
304 +{"name": "Adrian Perez de Castro", "address": "aperez@igalia.com", "name-addr": "Adrian Perez de Castro <aperez@igalia.com>", "count": 1}
\r
305 +{"name": "Alex Botero-Lowry", "address": "alex.boterolowry@gmail.com", "name-addr": "Alex Botero-Lowry <alex.boterolowry@gmail.com>", "count": 2}
\r
306 +{"name": "Alexander Botero-Lowry", "address": "alex.boterolowry@gmail.com", "name-addr": "Alexander Botero-Lowry <alex.boterolowry@gmail.com>", "count": 4}
\r
307 +{"name": "Aron Griffis", "address": "agriffis@n01se.net", "name-addr": "Aron Griffis <agriffis@n01se.net>", "count": 1}
\r
308 +{"name": "Carl Worth", "address": "cworth@cworth.org", "name-addr": "Carl Worth <cworth@cworth.org>", "count": 12}
\r
309 +{"name": "Chris Wilson", "address": "chris@chris-wilson.co.uk", "name-addr": "Chris Wilson <chris@chris-wilson.co.uk>", "count": 1}
\r
310 +{"name": "François Boulogne", "address": "boulogne.f@gmail.com", "name-addr": "François Boulogne <boulogne.f@gmail.com>", "count": 1}
\r
311 +{"name": "Ingmar Vanhassel", "address": "ingmar@exherbo.org", "name-addr": "Ingmar Vanhassel <ingmar@exherbo.org>", "count": 1}
\r
312 +{"name": "Israel Herraiz", "address": "isra@herraiz.org", "name-addr": "Israel Herraiz <isra@herraiz.org>", "count": 1}
\r
313 +{"name": "Jan Janak", "address": "jan@ryngle.com", "name-addr": "Jan Janak <jan@ryngle.com>", "count": 4}
\r
314 +{"name": "Jjgod Jiang", "address": "gzjjgod@gmail.com", "name-addr": "Jjgod Jiang <gzjjgod@gmail.com>", "count": 2}
\r
315 +{"name": "Keith Packard", "address": "keithp@keithp.com", "name-addr": "Keith Packard <keithp@keithp.com>", "count": 7}
\r
316 +{"name": "Lars Kellogg-Stedman", "address": "lars@seas.harvard.edu", "name-addr": "Lars Kellogg-Stedman <lars@seas.harvard.edu>", "count": 5}
\r
317 +{"name": "Mikhail Gusarov", "address": "dottedmag@dottedmag.net", "name-addr": "Mikhail Gusarov <dottedmag@dottedmag.net>", "count": 5}
\r
318 +{"name": "Olivier Berger", "address": "olivier.berger@it-sudparis.eu", "name-addr": "Olivier Berger <olivier.berger@it-sudparis.eu>", "count": 1}
\r
319 +{"name": "Rolland Santimano", "address": "rollandsantimano@yahoo.com", "name-addr": "Rolland Santimano <rollandsantimano@yahoo.com>", "count": 1}
\r
320 +{"name": "Stewart Smith", "address": "stewart@flamingspork.com", "name-addr": "Stewart Smith <stewart@flamingspork.com>", "count": 3}
\r
322 +test_expect_equal_file OUTPUT EXPECTED
\r