Re: Hi all
[notmuch-archives.git] / 0b / 7821cc2c5cc825f261347f589ba26d04e65726
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 5EB54431FDB\r
6         for <notmuch@notmuchmail.org>; Fri,  9 Jan 2015 08:31:37 -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: 0.138\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=0.138 tagged_above=-999 required=5\r
12         tests=[DNS_FROM_AHBL_RHSBL=2.438, RCVD_IN_DNSWL_MED=-2.3]\r
13         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 v-FuTaOBJyc4 for <notmuch@notmuchmail.org>;\r
17         Fri,  9 Jan 2015 08:31:32 -0800 (PST)\r
18 Received: from max.feld.cvut.cz (max.feld.cvut.cz [147.32.192.36])\r
19         by olra.theworths.org (Postfix) with ESMTP id A6A66431FD8\r
20         for <notmuch@notmuchmail.org>; Fri,  9 Jan 2015 08:31:32 -0800 (PST)\r
21 Received: from localhost (unknown [192.168.200.7])\r
22         by max.feld.cvut.cz (Postfix) with ESMTP id 841B73CFEF8;\r
23         Fri,  9 Jan 2015 17:31:27 +0100 (CET)\r
24 X-Virus-Scanned: IMAP STYX AMAVIS\r
25 Received: from max.feld.cvut.cz ([192.168.200.1])\r
26         by localhost (styx.feld.cvut.cz [192.168.200.7]) (amavisd-new,\r
27         port 10044)\r
28         with ESMTP id h_s2mZ4PUkMI; Fri,  9 Jan 2015 17:31:23 +0100 (CET)\r
29 Received: from imap.feld.cvut.cz (imap.feld.cvut.cz [147.32.192.34])\r
30         by max.feld.cvut.cz (Postfix) with ESMTP id 87A453CFEAD;\r
31         Fri,  9 Jan 2015 17:31:23 +0100 (CET)\r
32 Received: from wsh by steelpick.2x.cz with local (Exim 4.84)\r
33         (envelope-from <sojkam1@fel.cvut.cz>)\r
34         id 1Y9cT4-0006RW-Di; Fri, 09 Jan 2015 17:31:22 +0100\r
35 From: Michal Sojka <sojkam1@fel.cvut.cz>\r
36 To: Tomi Ollila <tomi.ollila@iki.fi>, David Bremner <david@tethera.net>,\r
37         notmuch@notmuchmail.org\r
38 Subject: Re: [PATCH v3 10/10] cli: address: Add --filter-by\r
39         option  to      configure       address filtering\r
40 In-Reply-To: <871tn46khe.fsf@steelpick.2x.cz>\r
41 References: <1415147159-19946-1-git-send-email-sojkam1@fel.cvut.cz>\r
42         <1415147159-19946-11-git-send-email-sojkam1@fel.cvut.cz>\r
43         <87vbkrfs66.fsf@maritornes.cs.unb.ca>\r
44         <m2d26yhfmk.fsf@guru.guru-group.fi>\r
45         <87egr46qcs.fsf@steelpick.2x.cz>\r
46         <m2h9w0ujo3.fsf@guru.guru-group.fi>\r
47         <871tn46khe.fsf@steelpick.2x.cz>\r
48 User-Agent: Notmuch/0.18.2+178~g6e9e8bb (http://notmuchmail.org) Emacs/24.4.1\r
49         (x86_64-pc-linux-gnu)\r
50 Date: Fri, 09 Jan 2015 17:31:22 +0100\r
51 Message-ID: <87y4pb6hlx.fsf@steelpick.2x.cz>\r
52 MIME-Version: 1.0\r
53 Content-Type: text/plain\r
54 X-BeenThere: notmuch@notmuchmail.org\r
55 X-Mailman-Version: 2.1.13\r
56 Precedence: list\r
57 List-Id: "Use and development of the notmuch mail system."\r
58         <notmuch.notmuchmail.org>\r
59 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
60         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
61 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
62 List-Post: <mailto:notmuch@notmuchmail.org>\r
63 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
64 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
65         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
66 X-List-Received-Date: Fri, 09 Jan 2015 16:31:37 -0000\r
67 \r
68 On Fri, Jan 09 2015, Michal Sojka wrote:\r
69 > On Fri, Jan 09 2015, Tomi Ollila wrote:\r
70 >> On Fri, Jan 09 2015, Michal Sojka <sojkam1@fel.cvut.cz> wrote:\r
71 >>\r
72 >>> Hi,\r
73 >>>\r
74 >>> sorry for longer response time :)\r
75 >>>\r
76 >>> On Thu, Jan 01 2015, Tomi Ollila wrote:\r
77 >>>> On Wed, Dec 31 2014, David Bremner <david@tethera.net> wrote:\r
78 >>>>\r
79 >>>>> Michal Sojka <sojkam1@fel.cvut.cz> writes:\r
80 >>>>>\r
81 >>>>>> This option allows to configure the criterion for duplicate address\r
82 >>>>>> filtering. Without this option, all unique combinations of name and\r
83 >>>>>> address parts are printed. This option allows to filter the output\r
84 >>>>>> more, for example to only contain unique address parts.\r
85 >>>>>\r
86 >>>>> I had the feeling there was some "controversy" about the UI here, but\r
87 >>>>> following back the 3 versions of the series I didn't see it. Does that\r
88 >>>>> mean we just need to sanity check the code, or are there outstanding\r
89 >>>>> bikes to shed?\r
90 >>>\r
91 >>> I'd tend to rename this option to --unique as it was in some previous\r
92 >>> version of the patch. Another thing in my mind is the implementation of\r
93 >>> the --complete option mentioned in id:878uid9qjl.fsf@nautilus.nautilus.\r
94 >>> This would also involve some kind of address filtering. I'll look into\r
95 >>> this and send patches later.\r
96 >>>\r
97 >>>> I have intentionally been guiet on this during the review process of the\r
98 >>>> other patches to not slow down the acceptance of the others. I have not\r
99 >>>> got enough time to look the implemenentation or think this last patch\r
100 >>>> further -- from the user interface point of view I recall seeing there\r
101 >>>> both useless features (but which might be warranted by implementation\r
102 >>>> simplicity) and missing features (but which might not be there due to\r
103 >>>> difficulty in implementation). Also, I am not sure whether the --filter-by\r
104 >>>> is good option (and options descriptive...)...\r
105 >>>\r
106 >>> I'd be interested in what are these "missing features".\r
107 >>\r
108 >> Last night when I tried to catch sleep I was also thinking of this...\r
109 >> ... let's see what I remember...\r
110 >>\r
111 >> First, Currently if we have addresses:\r
112 >>\r
113 >>  "Uni Que" <unique@example.org>\r
114 >>  "Uni Que" <Unique@Example.Org>\r
115 >>\r
116 >> I presume these are thought as a separate addresses -- and an option to\r
117 >> thought these as the same would be useful.\r
118 >\r
119 > Yes, this would correspond to --unique=addrfold or --unique=nameaddrfold\r
120 > from my patch.\r
121 >\r
122 >> but let's consider second set of addresses:\r
123 >>\r
124 >>  "Uni Que" <unique@example.org>\r
125 >>  "Uni Keko" <unique@example.org>\r
126 >>\r
127 >> Now, if there were an option to consider these 2 as the same, that would\r
128 >> hide user from one of the names -- It is clear that "Uni Que" is the right\r
129 >> one but if only "Uni Keko" (sleepyhead, that is) is shown user don't have\r
130 >> a choice to select the right one. I am not sure what the use case for\r
131 >> "uniquing" these 2 were.\r
132 >\r
133 > For example, when you are interested in the number of people involved in\r
134 > a discussion. You care only about the address and not about the names.\r
135 > Perhaps you'd like to see only the addresses in the output and not the\r
136 > names in this case, wouldn't you?\r
137 \r
138 I meant something like the patch bellow. Unique options would be\r
139 no/yes/yes-but-case-insensitive and the type of uniqueness would be\r
140 determined by the --output flags. I don't like one thing on this\r
141 approach: --output flags now determine visibility of both rows and\r
142 columns in the output. But this is already present in master, because we\r
143 have count column there.\r
144 \r
145 -Michal\r
146 \r
147 diff --git a/notmuch-search.c b/notmuch-search.c\r
148 index 14b9f01..760f59a 100644\r
149 --- a/notmuch-search.c\r
150 +++ b/notmuch-search.c\r
151 @@ -34,6 +34,8 @@ typedef enum {\r
152      OUTPUT_SENDER      = 1 << 5,\r
153      OUTPUT_RECIPIENTS  = 1 << 6,\r
154      OUTPUT_COUNT       = 1 << 7,\r
155 +    OUTPUT_NAME                = 1 << 8,\r
156 +    OUTPUT_ADDR                = 1 << 9,\r
157  } output_t;\r
158  \r
159  typedef enum {\r
160 @@ -43,6 +45,12 @@ typedef enum {\r
161      NOTMUCH_FORMAT_SEXP\r
162  } format_sel_t;\r
163  \r
164 +typedef enum {\r
165 +    UNIQUE_NO = 0,\r
166 +    UNIQUE_YES,\r
167 +    UNIQUE_CASEFOLD,\r
168 +} unique_t;\r
169 +\r
170  typedef struct {\r
171      notmuch_database_t *notmuch;\r
172      format_sel_t format_sel;\r
173 @@ -55,6 +63,7 @@ typedef struct {\r
174      int limit;\r
175      int dupe;\r
176      GHashTable *addresses;\r
177 +    unique_t unique;\r
178  } search_context_t;\r
179  \r
180  typedef struct {\r
181 @@ -243,18 +252,45 @@ do_search_threads (search_context_t *ctx)\r
182      return 0;\r
183  }\r
184  \r
185 -/* Returns TRUE iff name and addr is duplicate. If not, stores the\r
186 - * name/addr pair in order to detect subsequent duplicates. */\r
187 +/* Returns TRUE iff name and/or addr is considered duplicate. If not,\r
188 + * stores the name/addr pair in order to detect subsequent\r
189 + * duplicates. */\r
190  static notmuch_bool_t\r
191  is_duplicate (const search_context_t *ctx, const char *name, const char *addr)\r
192  {\r
193      notmuch_bool_t duplicate;\r
194      char *key;\r
195 +    gchar *addrfold = NULL;\r
196 +    gchar *namefold = NULL;\r
197      mailbox_t *mailbox;\r
198  \r
199 -    key = talloc_asprintf (ctx->format, "%s <%s>", name, addr);\r
200 +    if (ctx->unique == UNIQUE_CASEFOLD) {\r
201 +       addrfold = g_utf8_casefold (addr, -1);\r
202 +       namefold = g_utf8_casefold (name, -1);\r
203 +    }\r
204 +\r
205 +    switch (ctx->output & (OUTPUT_NAME | OUTPUT_ADDR)) {\r
206 +    case OUTPUT_NAME | OUTPUT_ADDR:\r
207 +       key = talloc_asprintf (ctx->format, "%s <%s>", namefold ? namefold : name,\r
208 +                                                      addrfold ? addrfold : addr);\r
209 +       break;\r
210 +    case OUTPUT_NAME:\r
211 +       key = talloc_strdup (ctx->format, namefold ? namefold : name); /* !name results in !key */\r
212 +       break;\r
213 +    case OUTPUT_ADDR:\r
214 +       key = talloc_strdup (ctx->format, addrfold ? addrfold : addr);\r
215 +       break;\r
216 +    default:\r
217 +       INTERNAL_ERROR("invalid --output flags");\r
218 +    }\r
219 +\r
220 +    if (addrfold) {\r
221 +       g_free (addrfold);\r
222 +       g_free (namefold);\r
223 +    }\r
224 +\r
225      if (! key)\r
226 -       return FALSE;\r
227 +       return TRUE;\r
228  \r
229      duplicate = g_hash_table_lookup_extended (ctx->addresses, key, NULL, (gpointer)&mailbox);\r
230  \r
231 @@ -281,6 +317,7 @@ print_mailbox (const search_context_t *ctx, const mailbox_t *mailbox)\r
232      sprinter_t *format = ctx->format;\r
233      InternetAddress *ia = internet_address_mailbox_new (name, addr);\r
234      char *name_addr;\r
235 +    notmuch_bool_t no_name_and_addr = !(ctx->output & OUTPUT_NAME || ctx->output & OUTPUT_ADDR); /* Backward compatible behavior */\r
236  \r
237      /* name_addr has the name part quoted if necessary. Compare\r
238       * 'John Doe <john@doe.com>' vs. '"Doe, John" <john@doe.com>' */\r
239 @@ -291,16 +328,27 @@ print_mailbox (const search_context_t *ctx, const mailbox_t *mailbox)\r
240             format->integer (format, count);\r
241             format->string (format, "\t");\r
242         }\r
243 -       format->string (format, name_addr);\r
244 +       if ((ctx->output & OUTPUT_NAME && ctx->output & OUTPUT_ADDR) || no_name_and_addr)\r
245 +           format->string (format, name_addr);\r
246 +       else if (ctx->output & OUTPUT_NAME)\r
247 +           format->string (format, name);\r
248 +       else if (ctx->output & OUTPUT_ADDR)\r
249 +           format->string (format, addr);\r
250         format->separator (format);\r
251      } else {\r
252         format->begin_map (format);\r
253 -       format->map_key (format, "name");\r
254 -       format->string (format, name);\r
255 -       format->map_key (format, "address");\r
256 -       format->string (format, addr);\r
257 -       format->map_key (format, "name-addr");\r
258 -       format->string (format, name_addr);\r
259 +       if (ctx->output & OUTPUT_NAME || no_name_and_addr) {\r
260 +           format->map_key (format, "name");\r
261 +           format->string (format, name);\r
262 +       }\r
263 +       if (ctx->output & OUTPUT_ADDR || no_name_and_addr) {\r
264 +           format->map_key (format, "address");\r
265 +           format->string (format, addr);\r
266 +       }\r
267 +       if ((ctx->output & OUTPUT_NAME && ctx->output & OUTPUT_ADDR) || no_name_and_addr) {\r
268 +           format->map_key (format, "name-addr");\r
269 +           format->string (format, name_addr);\r
270 +       }\r
271         if (count > 0) {\r
272             format->map_key (format, "count");\r
273             format->integer (format, count);\r
274 @@ -631,6 +679,7 @@ static search_context_t search_context = {\r
275      .offset = 0,\r
276      .limit = -1, /* unlimited */\r
277      .dupe = -1,\r
278 +    .unique = UNIQUE_NO,\r
279  };\r
280  \r
281  static const notmuch_opt_desc_t common_options[] = {\r
282 @@ -722,11 +771,18 @@ notmuch_address_command (notmuch_config_t *config, int argc, char *argv[])\r
283           (notmuch_keyword_t []){ { "sender", OUTPUT_SENDER },\r
284                                   { "recipients", OUTPUT_RECIPIENTS },\r
285                                   { "count", OUTPUT_COUNT },\r
286 +                                 { "name", OUTPUT_NAME },\r
287 +                                 { "addr", OUTPUT_ADDR },\r
288                                   { 0, 0 } } },\r
289         { NOTMUCH_OPT_KEYWORD, &ctx->exclude, "exclude", 'x',\r
290           (notmuch_keyword_t []){ { "true", NOTMUCH_EXCLUDE_TRUE },\r
291                                   { "false", NOTMUCH_EXCLUDE_FALSE },\r
292                                   { 0, 0 } } },\r
293 +       { NOTMUCH_OPT_KEYWORD, &ctx->unique, "unique", 'b',\r
294 +         (notmuch_keyword_t []){ { "no", UNIQUE_NO },\r
295 +                                 { "yes", UNIQUE_YES },\r
296 +                                 { "casefold", UNIQUE_CASEFOLD },\r
297 +                                 { 0, 0 } } },\r
298         { NOTMUCH_OPT_INHERIT, &common_options, NULL, 0, 0 },\r
299         { 0, 0, 0, 0, 0 }\r
300      };\r
301 \r