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 5B963431FAF
\r
6 for <notmuch@notmuchmail.org>; Tue, 4 Nov 2014 16:26:47 -0800 (PST)
\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 pNfXtKfdIBqS for <notmuch@notmuchmail.org>;
\r
16 Tue, 4 Nov 2014 16:26:40 -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 73513431FC2
\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 D07A05CD1A9
\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 W_4T4ZxuMijL for <notmuch@notmuchmail.org>;
\r
27 Wed, 5 Nov 2014 01:26:18 +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 DBA145CD1B1
\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-0005DI-0Y; 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 09/10] cli: address: Add --output=count
\r
37 Date: Wed, 5 Nov 2014 01:25:58 +0100
\r
38 Message-Id: <1415147159-19946-10-git-send-email-sojkam1@fel.cvut.cz>
\r
39 X-Mailer: git-send-email 2.1.1
\r
40 In-Reply-To: <1415147159-19946-1-git-send-email-sojkam1@fel.cvut.cz>
\r
41 References: <1415147159-19946-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: Wed, 05 Nov 2014 00:26:47 -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 | 11 ++++++++-
\r
65 notmuch-search.c | 49 ++++++++++++++++++++++++++++++++------
\r
66 test/T095-address.sh | 49 ++++++++++++++++++++++++++++++++++++++
\r
67 5 files changed, 103 insertions(+), 10 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 01eb811..359616e 100644
\r
97 --- a/doc/man1/notmuch-address.rst
\r
98 +++ b/doc/man1/notmuch-address.rst
\r
99 @@ -29,7 +29,7 @@ Supported options for **address** include
\r
100 intended for programs that invoke **notmuch(1)** internally. If
\r
101 omitted, the latest supported version will be used.
\r
103 - ``--output=(sender|recipients)``
\r
104 + ``--output=(sender|recipients|count)``
\r
106 Controls which information appears in the output. This option
\r
107 can be given multiple times to combine different outputs.
\r
108 @@ -48,6 +48,13 @@ Supported options for **address** include
\r
109 Output all addresses from the *To*, *Cc* and *Bcc*
\r
113 + Print the count of how many times was the address
\r
114 + encountered during search.
\r
116 + Note: With this option, addresses are printed only after
\r
117 + the whole search is finished. This may take long time.
\r
119 ``--sort=``\ (**newest-first**\ \|\ **oldest-first**)
\r
120 This option can be used to present results in either
\r
121 chronological order (**oldest-first**) or reverse chronological
\r
122 @@ -56,6 +63,8 @@ Supported options for **address** include
\r
123 By default, results will be displayed in reverse chronological
\r
124 order, (that is, the newest results will be displayed first).
\r
126 + This option has no effect when used with --output=count.
\r
128 ``--exclude=(true|false)``
\r
129 A message is called "excluded" if it matches at least one tag in
\r
130 search.tag\_exclude that does not appear explicitly in the
\r
131 diff --git a/notmuch-search.c b/notmuch-search.c
\r
132 index 86d54ba..5036d8e 100644
\r
133 --- a/notmuch-search.c
\r
134 +++ b/notmuch-search.c
\r
135 @@ -33,6 +33,7 @@ typedef enum {
\r
136 /* Address command */
\r
137 OUTPUT_SENDER = 1 << 5,
\r
138 OUTPUT_RECIPIENTS = 1 << 6,
\r
139 + OUTPUT_COUNT = 1 << 7,
\r
143 @@ -59,6 +60,7 @@ typedef struct {
\r
150 /* Return two stable query strings that identify exactly the matched
\r
151 @@ -248,17 +250,24 @@ is_duplicate (const search_context_t *ctx, const char *name, const char *addr)
\r
153 notmuch_bool_t duplicate;
\r
155 + mailbox_t *mailbox;
\r
157 key = talloc_asprintf (ctx->format, "%s <%s>", name, addr);
\r
161 - duplicate = g_hash_table_lookup_extended (ctx->addresses, key, NULL, NULL);
\r
162 + duplicate = g_hash_table_lookup_extended (ctx->addresses, key, NULL, (gpointer)&mailbox);
\r
165 - g_hash_table_insert (ctx->addresses, key, NULL);
\r
167 + if (! duplicate) {
\r
168 + mailbox = talloc (ctx->format, mailbox_t);
\r
169 + mailbox->name = talloc_strdup (mailbox, name);
\r
170 + mailbox->addr = talloc_strdup (mailbox, addr);
\r
171 + mailbox->count = 1;
\r
172 + g_hash_table_insert (ctx->addresses, key, mailbox);
\r
174 + mailbox->count++;
\r
180 @@ -268,6 +277,7 @@ print_mailbox (const search_context_t *ctx, const mailbox_t *mailbox)
\r
182 const char *name = mailbox->name;
\r
183 const char *addr = mailbox->addr;
\r
184 + int count = mailbox->count;
\r
185 sprinter_t *format = ctx->format;
\r
186 InternetAddress *ia = internet_address_mailbox_new (name, addr);
\r
188 @@ -277,6 +287,10 @@ print_mailbox (const search_context_t *ctx, const mailbox_t *mailbox)
\r
189 name_addr = internet_address_to_string (ia, FALSE);
\r
191 if (format->is_text_printer) {
\r
193 + format->integer (format, count);
\r
194 + format->string (format, "\t");
\r
196 format->string (format, name_addr);
\r
197 format->separator (format);
\r
199 @@ -287,6 +301,10 @@ print_mailbox (const search_context_t *ctx, const mailbox_t *mailbox)
\r
200 format->string (format, addr);
\r
201 format->map_key (format, "name-addr");
\r
202 format->string (format, name_addr);
\r
204 + format->map_key (format, "count");
\r
205 + format->integer (format, count);
\r
207 format->end (format);
\r
208 format->separator (format);
\r
210 @@ -295,7 +313,7 @@ print_mailbox (const search_context_t *ctx, const mailbox_t *mailbox)
\r
211 g_free (name_addr);
\r
214 -/* Print addresses from InternetAddressList. */
\r
215 +/* Print or prepare for printing addresses from InternetAddressList. */
\r
217 process_address_list (const search_context_t *ctx,
\r
218 InternetAddressList *list)
\r
219 @@ -320,17 +338,21 @@ process_address_list (const search_context_t *ctx,
\r
221 .name = internet_address_get_name (address),
\r
222 .addr = internet_address_mailbox_get_addr (mailbox),
\r
226 if (is_duplicate (ctx, mbx.name, mbx.addr))
\r
229 + if (ctx->output & OUTPUT_COUNT)
\r
232 print_mailbox (ctx, &mbx);
\r
237 -/* Print addresses from a message header. */
\r
238 +/* Print or prepare for printing addresses from a message header. */
\r
240 process_address_header (const search_context_t *ctx, const char *value)
\r
242 @@ -355,6 +377,15 @@ _talloc_free_for_g_hash (void *ptr)
\r
247 +print_hash_value (unused (gpointer key), gpointer value, gpointer user_data)
\r
249 + const mailbox_t *mailbox = value;
\r
250 + search_context_t *ctx = user_data;
\r
252 + print_mailbox (ctx, mailbox);
\r
256 _count_filenames (notmuch_message_t *message)
\r
258 @@ -450,6 +481,9 @@ do_search_messages (search_context_t *ctx)
\r
259 notmuch_message_destroy (message);
\r
262 + if (ctx->addresses && ctx->output & OUTPUT_COUNT)
\r
263 + g_hash_table_foreach (ctx->addresses, print_hash_value, ctx);
\r
265 notmuch_messages_destroy (messages);
\r
267 format->end (format);
\r
268 @@ -687,6 +721,7 @@ notmuch_address_command (notmuch_config_t *config, int argc, char *argv[])
\r
269 { NOTMUCH_OPT_KEYWORD_FLAGS, &ctx->output, "output", 'o',
\r
270 (notmuch_keyword_t []){ { "sender", OUTPUT_SENDER },
\r
271 { "recipients", OUTPUT_RECIPIENTS },
\r
272 + { "count", OUTPUT_COUNT },
\r
274 { NOTMUCH_OPT_KEYWORD, &ctx->exclude, "exclude", 'x',
\r
275 (notmuch_keyword_t []){ { "true", NOTMUCH_EXCLUDE_TRUE },
\r
276 @@ -708,7 +743,7 @@ notmuch_address_command (notmuch_config_t *config, int argc, char *argv[])
\r
277 return EXIT_FAILURE;
\r
279 ctx->addresses = g_hash_table_new_full (g_str_hash, g_str_equal,
\r
280 - _talloc_free_for_g_hash, NULL);
\r
281 + _talloc_free_for_g_hash, _talloc_free_for_g_hash);
\r
283 ret = do_search_messages (ctx);
\r
285 diff --git a/test/T095-address.sh b/test/T095-address.sh
\r
286 index 0d47c0d..033d0f4 100755
\r
287 --- a/test/T095-address.sh
\r
288 +++ b/test/T095-address.sh
\r
289 @@ -96,4 +96,53 @@ notmuch address '*' >OUTPUT
\r
290 # Use EXPECTED from previous subtest
\r
291 test_expect_equal_file OUTPUT EXPECTED
\r
293 +test_begin_subtest "--output=sender --output=count"
\r
294 +notmuch address --output=sender --output=count '*' | sort -n >OUTPUT
\r
295 +cat <<EOF >EXPECTED
\r
296 +1 Adrian Perez de Castro <aperez@igalia.com>
\r
297 +1 Aron Griffis <agriffis@n01se.net>
\r
298 +1 Chris Wilson <chris@chris-wilson.co.uk>
\r
299 +1 François Boulogne <boulogne.f@gmail.com>
\r
300 +1 Ingmar Vanhassel <ingmar@exherbo.org>
\r
301 +1 Israel Herraiz <isra@herraiz.org>
\r
302 +1 Olivier Berger <olivier.berger@it-sudparis.eu>
\r
303 +1 Rolland Santimano <rollandsantimano@yahoo.com>
\r
304 +2 Alex Botero-Lowry <alex.boterolowry@gmail.com>
\r
305 +2 Jjgod Jiang <gzjjgod@gmail.com>
\r
306 +3 Stewart Smith <stewart@flamingspork.com>
\r
307 +4 Alexander Botero-Lowry <alex.boterolowry@gmail.com>
\r
308 +4 Jan Janak <jan@ryngle.com>
\r
309 +5 Lars Kellogg-Stedman <lars@seas.harvard.edu>
\r
310 +5 Mikhail Gusarov <dottedmag@dottedmag.net>
\r
311 +7 Keith Packard <keithp@keithp.com>
\r
312 +12 Carl Worth <cworth@cworth.org>
\r
314 +test_expect_equal_file OUTPUT EXPECTED
\r
316 +test_begin_subtest "--output=sender --output=count --format=json"
\r
317 +# Since the iteration order of GHashTable is not specified, we
\r
318 +# preprocess and sort the results to keep the order stable here.
\r
319 +notmuch address --output=sender --output=count --format=json '*' | \
\r
320 + sed -e 's/^\[//' -e 's/]$//' -e 's/,$//' | sort >OUTPUT
\r
321 +cat <<EOF >EXPECTED
\r
322 +{"name": "Adrian Perez de Castro", "address": "aperez@igalia.com", "name-addr": "Adrian Perez de Castro <aperez@igalia.com>", "count": 1}
\r
323 +{"name": "Alex Botero-Lowry", "address": "alex.boterolowry@gmail.com", "name-addr": "Alex Botero-Lowry <alex.boterolowry@gmail.com>", "count": 2}
\r
324 +{"name": "Alexander Botero-Lowry", "address": "alex.boterolowry@gmail.com", "name-addr": "Alexander Botero-Lowry <alex.boterolowry@gmail.com>", "count": 4}
\r
325 +{"name": "Aron Griffis", "address": "agriffis@n01se.net", "name-addr": "Aron Griffis <agriffis@n01se.net>", "count": 1}
\r
326 +{"name": "Carl Worth", "address": "cworth@cworth.org", "name-addr": "Carl Worth <cworth@cworth.org>", "count": 12}
\r
327 +{"name": "Chris Wilson", "address": "chris@chris-wilson.co.uk", "name-addr": "Chris Wilson <chris@chris-wilson.co.uk>", "count": 1}
\r
328 +{"name": "François Boulogne", "address": "boulogne.f@gmail.com", "name-addr": "François Boulogne <boulogne.f@gmail.com>", "count": 1}
\r
329 +{"name": "Ingmar Vanhassel", "address": "ingmar@exherbo.org", "name-addr": "Ingmar Vanhassel <ingmar@exherbo.org>", "count": 1}
\r
330 +{"name": "Israel Herraiz", "address": "isra@herraiz.org", "name-addr": "Israel Herraiz <isra@herraiz.org>", "count": 1}
\r
331 +{"name": "Jan Janak", "address": "jan@ryngle.com", "name-addr": "Jan Janak <jan@ryngle.com>", "count": 4}
\r
332 +{"name": "Jjgod Jiang", "address": "gzjjgod@gmail.com", "name-addr": "Jjgod Jiang <gzjjgod@gmail.com>", "count": 2}
\r
333 +{"name": "Keith Packard", "address": "keithp@keithp.com", "name-addr": "Keith Packard <keithp@keithp.com>", "count": 7}
\r
334 +{"name": "Lars Kellogg-Stedman", "address": "lars@seas.harvard.edu", "name-addr": "Lars Kellogg-Stedman <lars@seas.harvard.edu>", "count": 5}
\r
335 +{"name": "Mikhail Gusarov", "address": "dottedmag@dottedmag.net", "name-addr": "Mikhail Gusarov <dottedmag@dottedmag.net>", "count": 5}
\r
336 +{"name": "Olivier Berger", "address": "olivier.berger@it-sudparis.eu", "name-addr": "Olivier Berger <olivier.berger@it-sudparis.eu>", "count": 1}
\r
337 +{"name": "Rolland Santimano", "address": "rollandsantimano@yahoo.com", "name-addr": "Rolland Santimano <rollandsantimano@yahoo.com>", "count": 1}
\r
338 +{"name": "Stewart Smith", "address": "stewart@flamingspork.com", "name-addr": "Stewart Smith <stewart@flamingspork.com>", "count": 3}
\r
340 +test_expect_equal_file OUTPUT EXPECTED
\r