Re: [PATCH v6 6/7] cli: search: Add --output=count
[notmuch-archives.git] / be / 094acc89dccecf9f6a2208dfc86b24ce73d249
1 Return-Path: <m.walters@qmul.ac.uk>\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 15CBA431FBC\r
6         for <notmuch@notmuchmail.org>; Fri, 31 Oct 2014 18:16:36 -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: -1.098\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-1.098 tagged_above=-999 required=5\r
12         tests=[DKIM_ADSP_CUSTOM_MED=0.001, FREEMAIL_FROM=0.001,\r
13         NML_ADSP_CUSTOM_MED=1.2, RCVD_IN_DNSWL_MED=-2.3] autolearn=disabled\r
14 Received: from olra.theworths.org ([127.0.0.1])\r
15         by localhost (olra.theworths.org [127.0.0.1]) (amavisd-new, port 10024)\r
16         with ESMTP id dVVFHYwpDjx9 for <notmuch@notmuchmail.org>;\r
17         Fri, 31 Oct 2014 18:16:28 -0700 (PDT)\r
18 Received: from mail2.qmul.ac.uk (mail2.qmul.ac.uk [138.37.6.6])\r
19         (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))\r
20         (No client certificate requested)\r
21         by olra.theworths.org (Postfix) with ESMTPS id 31D05431FAF\r
22         for <notmuch@notmuchmail.org>; Fri, 31 Oct 2014 18:16:28 -0700 (PDT)\r
23 Received: from smtp.qmul.ac.uk ([138.37.6.40])\r
24         by mail2.qmul.ac.uk with esmtp (Exim 4.71)\r
25         (envelope-from <m.walters@qmul.ac.uk>)\r
26         id 1XkNIo-0000nD-3j; Sat, 01 Nov 2014 01:16:26 +0000\r
27 Received: from 5751dfa2.skybroadband.com ([87.81.223.162] helo=localhost)\r
28         by smtp.qmul.ac.uk with esmtpsa (TLSv1:AES128-SHA:128) (Exim 4.71)\r
29         (envelope-from <m.walters@qmul.ac.uk>)\r
30         id 1XkNIn-0000D7-5O; Sat, 01 Nov 2014 01:16:25 +0000\r
31 From: Mark Walters <markwalters1009@gmail.com>\r
32 To: Michal Sojka <sojkam1@fel.cvut.cz>, notmuch@notmuchmail.org\r
33 Subject: Re: [PATCH v6 6/7] cli: search: Add --output=count\r
34 In-Reply-To: <1414792441-29555-7-git-send-email-sojkam1@fel.cvut.cz>\r
35 References: <1414792441-29555-1-git-send-email-sojkam1@fel.cvut.cz>\r
36         <1414792441-29555-7-git-send-email-sojkam1@fel.cvut.cz>\r
37 User-Agent: Notmuch/0.18.1+86~gef5e66a (http://notmuchmail.org) Emacs/23.4.1\r
38         (x86_64-pc-linux-gnu)\r
39 Date: Sat, 01 Nov 2014 01:16:20 +0000\r
40 Message-ID: <87r3xnu3dn.fsf@qmul.ac.uk>\r
41 MIME-Version: 1.0\r
42 Content-Type: text/plain; charset=us-ascii\r
43 X-Sender-Host-Address: 87.81.223.162\r
44 X-QM-Geographic: According to ripencc,\r
45         this message was delivered by a machine in Britain (UK) (GB).\r
46 X-QM-SPAM-Info: Sender has good ham record.  :)\r
47 X-QM-Body-MD5: b0db5e32fd3b8eeef637529a8567f93c (of first 20000 bytes)\r
48 X-SpamAssassin-Score: -0.1\r
49 X-SpamAssassin-SpamBar: /\r
50 X-SpamAssassin-Report: The QM spam filters have analysed this message to\r
51         determine if it is\r
52         spam. We require at least 5.0 points to mark a message as spam.\r
53         This message scored -0.1 points.\r
54         Summary of the scoring: \r
55         * 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail\r
56         provider *      (markwalters1009[at]gmail.com)\r
57         * -0.1 AWL AWL: From: address is in the auto white-list\r
58 X-QM-Scan-Virus: ClamAV says the message is clean\r
59 X-BeenThere: notmuch@notmuchmail.org\r
60 X-Mailman-Version: 2.1.13\r
61 Precedence: list\r
62 List-Id: "Use and development of the notmuch mail system."\r
63         <notmuch.notmuchmail.org>\r
64 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
65         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
66 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
67 List-Post: <mailto:notmuch@notmuchmail.org>\r
68 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
69 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
70         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
71 X-List-Received-Date: Sat, 01 Nov 2014 01:16:36 -0000\r
72 \r
73 \r
74 On Fri, 31 Oct 2014, Michal Sojka <sojkam1@fel.cvut.cz> wrote:\r
75 > This output can be used with --output=recipients or --output=sender\r
76 > and in addition to the addresses, it prints how many times was each\r
77 > address encountered during search.\r
78 \r
79 Hi\r
80 \r
81 I have a couple comments on this patch.\r
82 \r
83 > ---\r
84 >  completion/notmuch-completion.bash |  2 +-\r
85 >  completion/notmuch-completion.zsh  |  2 +-\r
86 >  doc/man1/notmuch-search.rst        |  9 +++++--\r
87 >  notmuch-search.c                   | 51 ++++++++++++++++++++++++++++++++------\r
88 >  4 files changed, 52 insertions(+), 12 deletions(-)\r
89 >\r
90 > diff --git a/completion/notmuch-completion.bash b/completion/notmuch-completion.bash\r
91 > index cfbd389..39cd829 100644\r
92 > --- a/completion/notmuch-completion.bash\r
93 > +++ b/completion/notmuch-completion.bash\r
94 > @@ -294,7 +294,7 @@ _notmuch_search()\r
95 >           return\r
96 >           ;;\r
97 >       --output)\r
98 > -         COMPREPLY=( $( compgen -W "summary threads messages files tags sender recipients" -- "${cur}" ) )\r
99 > +         COMPREPLY=( $( compgen -W "summary threads messages files tags sender recipients count" -- "${cur}" ) )\r
100 >           return\r
101 >           ;;\r
102 >       --sort)\r
103 > diff --git a/completion/notmuch-completion.zsh b/completion/notmuch-completion.zsh\r
104 > index 3e52a00..d7e5a5e 100644\r
105 > --- a/completion/notmuch-completion.zsh\r
106 > +++ b/completion/notmuch-completion.zsh\r
107 > @@ -53,7 +53,7 @@ _notmuch_search()\r
108 >      '--max-threads=[display only the first x threads from the search results]:number of threads to show: ' \\r
109 >      '--first=[omit the first x threads from the search results]:number of threads to omit: ' \\r
110 >      '--sort=[sort results]:sorting:((newest-first\:"reverse chronological order" oldest-first\:"chronological order"))' \\r
111 > -    '--output=[select what to output]:output:((summary threads messages files tags sender recipients))'\r
112 > +    '--output=[select what to output]:output:((summary threads messages files tags sender recipients count))'\r
113 >  }\r
114 >  \r
115 >  _notmuch()\r
116 > diff --git a/doc/man1/notmuch-search.rst b/doc/man1/notmuch-search.rst\r
117 > index 42f17e4..ec89200 100644\r
118 > --- a/doc/man1/notmuch-search.rst\r
119 > +++ b/doc/man1/notmuch-search.rst\r
120 > @@ -96,9 +96,14 @@ Supported options for **search** include\r
121 >              Like **sender** but for addresses from *To*, *Cc* and\r
122 >           *Bcc* headers.\r
123 >  \r
124 > +     **count**\r
125 > +         Can be used in combination with **sender** or\r
126 > +         **recipients** to print the count of how many times was\r
127 > +         the address encountered during search.\r
128 > +\r
129 >       This option can be given multiple times to combine different\r
130 > -     outputs. Currently, this is only supported for **sender** and\r
131 > -     **recipients** outputs.\r
132 > +     outputs. Currently, this is only supported for **sender**,\r
133 > +     **recipients** and **count** outputs.\r
134 \r
135 It might be worth saying that the results will be slower if count is\r
136 specified.\r
137 \r
138 >      ``--sort=``\ (**newest-first**\ \|\ **oldest-first**)\r
139 \r
140 I think sort works as expected if count is not specified, but does not\r
141 with count. Maybe count can be done by doing two passes? If it is\r
142 difficult it might be sufficient to just document that sort has no\r
143 effect.\r
144 \r
145 Best wishes\r
146 \r
147 Mark\r
148 \r
149 \r
150 \r
151 >          This option can be used to present results in either\r
152 > diff --git a/notmuch-search.c b/notmuch-search.c\r
153 > index 43d42c6..4b39dfc 100644\r
154 > --- a/notmuch-search.c\r
155 > +++ b/notmuch-search.c\r
156 > @@ -30,9 +30,10 @@ typedef enum {\r
157 >      OUTPUT_TAGS              = 1 << 4,\r
158 >      OUTPUT_SENDER    = 1 << 5,\r
159 >      OUTPUT_RECIPIENTS        = 1 << 6,\r
160 > +    OUTPUT_COUNT     = 1 << 7,\r
161 >  } output_t;\r
162 >  \r
163 > -#define OUTPUT_ADDRESS_FLAGS (OUTPUT_SENDER | OUTPUT_RECIPIENTS)\r
164 > +#define OUTPUT_ADDRESS_FLAGS (OUTPUT_SENDER | OUTPUT_RECIPIENTS | OUTPUT_COUNT)\r
165 >  \r
166 >  typedef struct {\r
167 >      sprinter_t *format;\r
168 > @@ -47,6 +48,7 @@ typedef struct {\r
169 >  typedef struct {\r
170 >      const char *name;\r
171 >      const char *addr;\r
172 > +    int count;\r
173 >  } mailbox_t;\r
174 >  \r
175 >  /* Return two stable query strings that identify exactly the matched\r
176 > @@ -235,17 +237,24 @@ is_duplicate (const search_options_t *opt, GHashTable *addrs, const char *name,\r
177 >  {\r
178 >      notmuch_bool_t duplicate;\r
179 >      char *key;\r
180 > +    mailbox_t *mailbox;\r
181 >  \r
182 >      key = talloc_asprintf (opt->format, "%s <%s>", name, addr);\r
183 >      if (! key)\r
184 >       return FALSE;\r
185 >  \r
186 > -    duplicate = g_hash_table_lookup_extended (addrs, key, NULL, NULL);\r
187 > +    duplicate = g_hash_table_lookup_extended (addrs, key, NULL, (gpointer)&mailbox);\r
188 >  \r
189 > -    if (! duplicate)\r
190 > -     g_hash_table_insert (addrs, key, NULL);\r
191 > -    else\r
192 > +    if (! duplicate) {\r
193 > +     mailbox = talloc (opt->format, mailbox_t);\r
194 > +     mailbox->name = talloc_strdup (mailbox, name);\r
195 > +     mailbox->addr = talloc_strdup (mailbox, addr);\r
196 > +     mailbox->count = 1;\r
197 > +     g_hash_table_insert (addrs, key, mailbox);\r
198 > +    } else {\r
199 > +     mailbox->count++;\r
200 >       talloc_free (key);\r
201 > +    }\r
202 >  \r
203 >      return duplicate;\r
204 >  }\r
205 > @@ -255,6 +264,7 @@ print_mailbox (const search_options_t *opt, const mailbox_t *mailbox)\r
206 >  {\r
207 >      const char *name = mailbox->name;\r
208 >      const char *addr = mailbox->addr;\r
209 > +    int count = mailbox->count;\r
210 >      sprinter_t *format = opt->format;\r
211 >      InternetAddress *ia = internet_address_mailbox_new (name, addr);\r
212 >      char *name_addr;\r
213 > @@ -264,6 +274,10 @@ print_mailbox (const search_options_t *opt, const mailbox_t *mailbox)\r
214 >      name_addr = internet_address_to_string (ia, FALSE);\r
215 >  \r
216 >      if (format->is_text_printer) {\r
217 > +     if (count > 0) {\r
218 > +         format->integer (format, count);\r
219 > +         format->string (format, "\t");\r
220 > +     }\r
221 >       format->string (format, name_addr);\r
222 >       format->separator (format);\r
223 >      } else {\r
224 > @@ -274,6 +288,10 @@ print_mailbox (const search_options_t *opt, const mailbox_t *mailbox)\r
225 >       format->string (format, addr);\r
226 >       format->map_key (format, "name-addr");\r
227 >       format->string (format, name_addr);\r
228 > +     if (count > 0) {\r
229 > +         format->map_key (format, "count");\r
230 > +         format->integer (format, count);\r
231 > +     }\r
232 >       format->end (format);\r
233 >       format->separator (format);\r
234 >      }\r
235 > @@ -282,7 +300,7 @@ print_mailbox (const search_options_t *opt, const mailbox_t *mailbox)\r
236 >      g_free (name_addr);\r
237 >  }\r
238 >  \r
239 > -/* Print addresses from InternetAddressList.  */\r
240 > +/* Print or prepare for printing addresses from InternetAddressList. */\r
241 >  static void\r
242 >  process_address_list (const search_options_t *opt, GHashTable *addrs,\r
243 >                     InternetAddressList *list)\r
244 > @@ -307,17 +325,21 @@ process_address_list (const search_options_t *opt, GHashTable *addrs,\r
245 >           mailbox_t mbx = {\r
246 >               .name = internet_address_get_name (address),\r
247 >               .addr = internet_address_mailbox_get_addr (mailbox),\r
248 > +             .count = 0,\r
249 >           };\r
250 >  \r
251 >           if (is_duplicate (opt, addrs, mbx.name, mbx.addr))\r
252 >               continue;\r
253 >  \r
254 > +         if (opt->output & OUTPUT_COUNT)\r
255 > +             continue;\r
256 > +\r
257 >           print_mailbox (opt, &mbx);\r
258 >       }\r
259 >      }\r
260 >  }\r
261 >  \r
262 > -/* Print addresses from a message header.  */\r
263 > +/* Print or prepare for printing addresses from a message header. */\r
264 >  static void\r
265 >  process_address_header (const search_options_t *opt, GHashTable *addrs, const char *value)\r
266 >  {\r
267 > @@ -341,6 +363,15 @@ _my_talloc_free_for_g_hash (void *ptr)\r
268 >      talloc_free (ptr);\r
269 >  }\r
270 >  \r
271 > +static void\r
272 > +print_hash_value (unused (gpointer key), gpointer value, gpointer user_data)\r
273 > +{\r
274 > +    const mailbox_t *mailbox = value;\r
275 > +    search_options_t *opt = user_data;\r
276 > +\r
277 > +    print_mailbox (opt, mailbox);\r
278 > +}\r
279 > +\r
280 >  static int\r
281 >  do_search_messages (search_options_t *opt)\r
282 >  {\r
283 > @@ -353,7 +384,7 @@ do_search_messages (search_options_t *opt)\r
284 >  \r
285 >      if (opt->output & OUTPUT_ADDRESS_FLAGS)\r
286 >       addresses = g_hash_table_new_full (g_str_hash, g_str_equal,\r
287 > -                                        _my_talloc_free_for_g_hash, NULL);\r
288 > +                                        _my_talloc_free_for_g_hash, _my_talloc_free_for_g_hash);\r
289 >  \r
290 >      if (opt->offset < 0) {\r
291 >       opt->offset += notmuch_query_count_messages (opt->query);\r
292 > @@ -420,6 +451,9 @@ do_search_messages (search_options_t *opt)\r
293 >       notmuch_message_destroy (message);\r
294 >      }\r
295 >  \r
296 > +    if (addresses && opt->output & OUTPUT_COUNT)\r
297 > +     g_hash_table_foreach (addresses, print_hash_value, opt);\r
298 > +\r
299 >      if (addresses)\r
300 >       g_hash_table_unref (addresses);\r
301 >  \r
302 > @@ -522,6 +556,7 @@ notmuch_search_command (notmuch_config_t *config, int argc, char *argv[])\r
303 >                                 { "recipients", OUTPUT_RECIPIENTS },\r
304 >                                 { "files", OUTPUT_FILES },\r
305 >                                 { "tags", OUTPUT_TAGS },\r
306 > +                               { "count", OUTPUT_COUNT },\r
307 >                                 { 0, 0 } } },\r
308 >          { NOTMUCH_OPT_KEYWORD, &exclude, "exclude", 'x',\r
309 >            (notmuch_keyword_t []){ { "true", NOTMUCH_EXCLUDE_TRUE },\r
310 > -- \r
311 > 2.1.1\r
312 >\r
313 > _______________________________________________\r
314 > notmuch mailing list\r
315 > notmuch@notmuchmail.org\r
316 > http://notmuchmail.org/mailman/listinfo/notmuch\r