Re: [PATCH] emacs: wash: make word-wrap bound message width
[notmuch-archives.git] / 71 / a52984f9353c127c43c002d53ab8ac1f362a1f
1 Return-Path: <amdragon@mit.edu>\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 F4063429E26\r
6         for <notmuch@notmuchmail.org>; Wed, 11 Jan 2012 19:31:44 -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.7\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-0.7 tagged_above=-999 required=5\r
12         tests=[RCVD_IN_DNSWL_LOW=-0.7] 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 K2lovlkmzSay for <notmuch@notmuchmail.org>;\r
16         Wed, 11 Jan 2012 19:31:43 -0800 (PST)\r
17 Received: from dmz-mailsec-scanner-7.mit.edu (DMZ-MAILSEC-SCANNER-7.MIT.EDU\r
18         [18.7.68.36])\r
19         by olra.theworths.org (Postfix) with ESMTP id 70A14429E25\r
20         for <notmuch@notmuchmail.org>; Wed, 11 Jan 2012 19:31:43 -0800 (PST)\r
21 X-AuditID: 12074424-b7fae6d000000906-71-4f0e541ed366\r
22 Received: from mailhub-auth-4.mit.edu ( [18.7.62.39])\r
23         by dmz-mailsec-scanner-7.mit.edu (Symantec Messaging Gateway) with SMTP\r
24         id CA.96.02310.E145E0F4; Wed, 11 Jan 2012 22:31:42 -0500 (EST)\r
25 Received: from outgoing.mit.edu (OUTGOING-AUTH.MIT.EDU [18.7.22.103])\r
26         by mailhub-auth-4.mit.edu (8.13.8/8.9.2) with ESMTP id q0C3VgC3005143; \r
27         Wed, 11 Jan 2012 22:31:42 -0500\r
28 Received: from awakening.csail.mit.edu (awakening.csail.mit.edu [18.26.4.91])\r
29         (authenticated bits=0)\r
30         (User authenticated as amdragon@ATHENA.MIT.EDU)\r
31         by outgoing.mit.edu (8.13.6/8.12.4) with ESMTP id q0C3VfCd012853\r
32         (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NOT);\r
33         Wed, 11 Jan 2012 22:31:42 -0500 (EST)\r
34 Received: from amthrax by awakening.csail.mit.edu with local (Exim 4.77)\r
35         (envelope-from <amdragon@mit.edu>)\r
36         id 1RlBOE-0004g9-O7; Wed, 11 Jan 2012 22:31:46 -0500\r
37 Date: Wed, 11 Jan 2012 22:31:46 -0500\r
38 From: Austin Clements <amdragon@MIT.EDU>\r
39 To: Jani Nikula <jani@nikula.org>\r
40 Subject: Re: [PATCH v3 1/4] cli: add support for replying just to the sender\r
41         in "notmuch reply"\r
42 Message-ID: <20120112033146.GU20796@mit.edu>\r
43 References: <cover.1325794371.git.jani@nikula.org>\r
44         <cover.1326224339.git.jani@nikula.org>\r
45         <d32e63c8115b1f2868acf96c83b30697be88ff10.1326224339.git.jani@nikula.org>\r
46 MIME-Version: 1.0\r
47 Content-Type: text/plain; charset=us-ascii\r
48 Content-Disposition: inline\r
49 In-Reply-To:\r
50  <d32e63c8115b1f2868acf96c83b30697be88ff10.1326224339.git.jani@nikula.org>\r
51 User-Agent: Mutt/1.5.21 (2010-09-15)\r
52 X-Brightmail-Tracker:\r
53  H4sIAAAAAAAAA+NgFmphleLIzCtJLcpLzFFi42IRYrdT15UL4fM3uLfVyqJpurPF9ZszmR2Y\r
54         PG7df83u8WzVLeYApigum5TUnMyy1CJ9uwSujMdzPjMVPE2r+L+7nbWBca1/FyMnh4SAicT0\r
55         C6dYIWwxiQv31rN1MXJxCAnsY5T4Nn0zM4SzgVFi9bZ5UM5JJokJl78wQjhLGCV6Z3Wyg/Sz\r
56         CKhKNLV2MoLYbAIaEtv2LwezRQQUJTaf3A9mMwtIS3z73cwEYgsLJErMv/IULM4roCNx5Ndd\r
57         JoihyxklFu+9wgaREJQ4OfMJC0SzlsSNfy+BijjABi3/xwES5hQIk1j2cBFYuaiAisSUk9vY\r
58         JjAKzULSPQtJ9yyE7gWMzKsYZVNyq3RzEzNzilOTdYuTE/PyUot0zfVyM0v0UlNKNzGCA9tF\r
59         ZQdj8yGlQ4wCHIxKPLw79vL6C7EmlhVX5h5ilORgUhLlXRbE5y/El5SfUpmRWJwRX1Sak1p8\r
60         iFGCg1lJhNepBqicNyWxsiq1KB8mJc3BoiTOq6H1zk9IID2xJDU7NbUgtQgmK8PBoSTBOzMY\r
61         aKhgUWp6akVaZk4JQpqJgxNkOA/Q8BCQGt7igsTc4sx0iPwpRkUpcd5ckIQASCKjNA+uF5Z4\r
62         XjGKA70izDsdpIoHmLTgul8BDWYCGrxlHQ/I4JJEhJRUA+O+N3selmdmiP41l7I9GLiitkLr\r
63         w6OEmwcCFT6E/gjabaDw62zKMfbbp1dExi/a9bCngH1Bk5CS8ePDXwX0G19Nu3XqqIRGRYc8\r
64         6/wTPHevPdcxsmtSNr3cvuvjrP+l0/5MLm7rzW8wlZbMWt24fXNHocHGon8Xj7PErzw/ebHz\r
65         komsmaK7t3QosRRnJBpqMRcVJwIAPCqbnhcDAAA=\r
66 Cc: notmuch@notmuchmail.org\r
67 X-BeenThere: notmuch@notmuchmail.org\r
68 X-Mailman-Version: 2.1.13\r
69 Precedence: list\r
70 List-Id: "Use and development of the notmuch mail system."\r
71         <notmuch.notmuchmail.org>\r
72 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
73         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
74 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
75 List-Post: <mailto:notmuch@notmuchmail.org>\r
76 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
77 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
78         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
79 X-List-Received-Date: Thu, 12 Jan 2012 03:31:45 -0000\r
80 \r
81 Quoth Jani Nikula on Jan 10 at  9:54 pm:\r
82 > Add new option --reply-to=(all|sender) to "notmuch reply" to select whether\r
83 > to reply to all (sender and all recipients), or just sender. Reply to all\r
84 > remains the default.\r
85\r
86 > Credits to Mark Walters <markwalters1009@gmail.com> for his similar earlier\r
87 > work where I picked up the basic idea of handling reply-to-sender in\r
88 > add_recipients_from_message(). All bugs are mine, though.\r
89\r
90 > Signed-off-by: Jani Nikula <jani@nikula.org>\r
91\r
92 > ---\r
93\r
94 > Settled on --reply-to=(all|sender) per Carl's earlier suggestion\r
95 > (id:87pqn5cg4g.fsf@yoom.home.cworth.org) and David's approval on IRC.\r
96 > ---\r
97 >  man/man1/notmuch-reply.1 |   28 +++++++++++++++---\r
98 >  notmuch-reply.c          |   70 ++++++++++++++++++++++++++++++++++-----------\r
99 >  2 files changed, 76 insertions(+), 22 deletions(-)\r
100\r
101 > diff --git a/man/man1/notmuch-reply.1 b/man/man1/notmuch-reply.1\r
102 > index db464d8..5160ece 100644\r
103 > --- a/man/man1/notmuch-reply.1\r
104 > +++ b/man/man1/notmuch-reply.1\r
105 > @@ -14,11 +14,13 @@ Constructs a reply template for a set of messages.\r
106 >  To make replying to email easier,\r
107 >  .B notmuch reply\r
108 >  takes an existing set of messages and constructs a suitable mail\r
109 > -template. The Reply-to header (if any, otherwise From:) is used for\r
110 > -the To: address. Vales from the To: and Cc: headers are copied, but\r
111 > -not including any of the current user's email addresses (as configured\r
112 > -in primary_mail or other_email in the .notmuch\-config file) in the\r
113 > -recipient list\r
114 > +template. The Reply-to: header (if any, otherwise From:) is used for\r
115 > +the To: address. Unless\r
116 > +.BR \-\-reply-to=sender\r
117 > +is specified, values from the To: and Cc: headers are copied, but not\r
118 > +including any of the current user's email addresses (as configured in\r
119 > +primary_mail or other_email in the .notmuch\-config file) in the\r
120 > +recipient list.\r
121 >  \r
122 >  It also builds a suitable new subject, including Re: at the front (if\r
123 >  not already present), and adding the message IDs of the messages being\r
124 > @@ -45,6 +47,22 @@ Includes subject and quoted message body.\r
125 >  Only produces In\-Reply\-To, References, To, Cc, and Bcc headers.\r
126 >  .RE\r
127 >  .RE\r
128 > +.RS\r
129 > +.TP 4\r
130 > +.BR \-\-reply\-to= ( all | sender )\r
131 > +.RS\r
132 > +.TP 4\r
133 > +.BR all " (default)"\r
134 > +Replies to all addresses.\r
135 > +.TP 4\r
136 > +.BR sender\r
137 > +Replies only to the sender. If replying to user's own message\r
138 > +(Reply-to: or From: header is one of the user's configured email\r
139 > +addresses), try To:, Cc:, and Bcc: headers in this order, and copy\r
140 > +values from the first that contains something other than only the\r
141 > +user's addresses.\r
142 > +.RE\r
143 > +.RE\r
144 >  \r
145 >  See \fBnotmuch-search-terms\fR(7)\r
146 >  for details of the supported syntax for <search-terms>.\r
147 > diff --git a/notmuch-reply.c b/notmuch-reply.c\r
148 > index 000f6da..7b785a7 100644\r
149 > --- a/notmuch-reply.c\r
150 > +++ b/notmuch-reply.c\r
151 > @@ -170,7 +170,7 @@ address_is_users (const char *address, notmuch_config_t *config)\r
152 >  \r
153 >  /* For each address in 'list' that is not configured as one of the\r
154 >   * user's addresses in 'config', add that address to 'message' as an\r
155 > - * address of 'type'.\r
156 > + * address of 'type', if 'add' is true.\r
157 \r
158 I puzzled over this for a while before I figured out what was actually\r
159 going on here.  I was confused because this comment makes it sound\r
160 like this function doesn't do what its name says if 'add' is false.\r
161 And, in fact, it doesn't!\r
162 \r
163 I understand from an evolutionary standpoint why the code works this\r
164 way, but at the very least, I think the comment should call out this\r
165 peculiarity.  Better might be to rename the function, since it's now\r
166 more general purpose than adding recipients for an address list, and\r
167 possibly change its API slightly to reflect its generality.  Off the\r
168 top of my head, I'm thinking something like\r
169 \r
170 /* Scan address list 'list'.\r
171  *\r
172  * If 'add' is non-NULL, then for each address in 'list' that is not\r
173  * configured as one of the user's addresses in 'config', add that\r
174  * address to 'message' as an address of 'type'.  If any addresses are\r
175  * added, set *added_ret to TRUE.\r
176  *\r
177  * If one of the user's addresses is encountered in 'list' and\r
178  * *user_addr_ret is not NULL, set *user_addr_ret to this address.\r
179  */\r
180 static void\r
181 scan_address_list (InternetAddressList *list,\r
182                    notmuch_config_t *config,\r
183                    GMimeMessage *add, GMimeRecipientType add_type,\r
184                    notmuch_bool_t *added_ret,\r
185                    const char **user_addr_ret)\r
186 \r
187 (The reason for added_ret is below.)  This would barely change the\r
188 code (in fact, it would simplify the handling of from_addr), but I\r
189 think it would make the function less misleading.\r
190 \r
191 >   *\r
192 >   * The first address encountered that *is* the user's address will be\r
193 >   * returned, (otherwise NULL is returned).\r
194 > @@ -179,7 +179,8 @@ static const char *\r
195 >  add_recipients_for_address_list (GMimeMessage *message,\r
196 >                                notmuch_config_t *config,\r
197 >                                GMimeRecipientType type,\r
198 > -                              InternetAddressList *list)\r
199 > +                              InternetAddressList *list,\r
200 > +                              notmuch_bool_t add)\r
201 >  {\r
202 >      InternetAddress *address;\r
203 >      int i;\r
204 > @@ -197,7 +198,7 @@ add_recipients_for_address_list (GMimeMessage *message,\r
205 >               continue;\r
206 >  \r
207 >           add_recipients_for_address_list (message, config,\r
208 > -                                          type, group_list);\r
209 > +                                          type, group_list, add);\r
210 >       } else {\r
211 >           InternetAddressMailbox *mailbox;\r
212 >           const char *name;\r
213 > @@ -211,7 +212,7 @@ add_recipients_for_address_list (GMimeMessage *message,\r
214 >           if (address_is_users (addr, config)) {\r
215 >               if (ret == NULL)\r
216 >                   ret = addr;\r
217 > -         } else {\r
218 > +         } else if (add) {\r
219 >               g_mime_message_add_recipient (message, type, name, addr);\r
220 >           }\r
221 >       }\r
222 > @@ -222,7 +223,7 @@ add_recipients_for_address_list (GMimeMessage *message,\r
223 >  \r
224 >  /* For each address in 'recipients' that is not configured as one of\r
225 >   * the user's addresses in 'config', add that address to 'message' as\r
226 > - * an address of 'type'.\r
227 > + * an address of 'type', if 'add' is true.\r
228 >   *\r
229 >   * The first address encountered that *is* the user's address will be\r
230 >   * returned, (otherwise NULL is returned).\r
231 > @@ -231,7 +232,8 @@ static const char *\r
232 >  add_recipients_for_string (GMimeMessage *message,\r
233 >                          notmuch_config_t *config,\r
234 >                          GMimeRecipientType type,\r
235 > -                        const char *recipients)\r
236 > +                        const char *recipients,\r
237 > +                        notmuch_bool_t add)\r
238 >  {\r
239 >      InternetAddressList *list;\r
240 >  \r
241 > @@ -242,7 +244,7 @@ add_recipients_for_string (GMimeMessage *message,\r
242 >      if (list == NULL)\r
243 >       return NULL;\r
244 >  \r
245 > -    return add_recipients_for_address_list (message, config, type, list);\r
246 > +    return add_recipients_for_address_list (message, config, type, list, add);\r
247 >  }\r
248 >  \r
249 >  /* Does the address in the Reply-To header of 'message' already appear\r
250 > @@ -286,13 +288,19 @@ reply_to_header_is_redundant (notmuch_message_t *message)\r
251 >  \r
252 >  /* Augments the recipients of reply from the headers of message.\r
253 >   *\r
254 > + * If 'reply_all' is true, use sender and all recipients, otherwise use the\r
255 > + * first header that contains something other than the user's addresses\r
256 \r
257 Since there's no context here, perhaps you could elaborate on "first\r
258 header"?  Maybe ".. otherwise scan the reply-to, from, to, cc, and bcc\r
259 headers for the first that contains something other than the user's\r
260 addresses and add the recipients from this header (typically ..".\r
261 \r
262 > + * (typically this would be reply-to-sender, but also handles reply to user's\r
263 > + * own message in a sensible way).\r
264 > + *\r
265 >   * If any of the user's addresses were found in these headers, the first\r
266 >   * of these returned, otherwise NULL is returned.\r
267 >   */\r
268 >  static const char *\r
269 >  add_recipients_from_message (GMimeMessage *reply,\r
270 >                            notmuch_config_t *config,\r
271 > -                          notmuch_message_t *message)\r
272 > +                          notmuch_message_t *message,\r
273 > +                          notmuch_bool_t reply_all)\r
274 >  {\r
275 >      struct {\r
276 >       const char *header;\r
277 > @@ -305,6 +313,7 @@ add_recipients_from_message (GMimeMessage *reply,\r
278 >       { "bcc",        NULL, GMIME_RECIPIENT_TYPE_BCC }\r
279 >      };\r
280 >      const char *from_addr = NULL;\r
281 > +    notmuch_bool_t add_recipients = TRUE;\r
282 >      unsigned int i;\r
283 >  \r
284 >      /* Some mailing lists munge the Reply-To header despite it being A Bad\r
285 > @@ -325,6 +334,7 @@ add_recipients_from_message (GMimeMessage *reply,\r
286 >  \r
287 >      for (i = 0; i < ARRAY_SIZE (reply_to_map); i++) {\r
288 >       const char *addr, *recipients;\r
289 > +     GMimeRecipientType recipient_type = reply_to_map[i].recipient_type;\r
290 >  \r
291 >       recipients = notmuch_message_get_header (message,\r
292 >                                                reply_to_map[i].header);\r
293 > @@ -332,11 +342,29 @@ add_recipients_from_message (GMimeMessage *reply,\r
294 >           recipients = notmuch_message_get_header (message,\r
295 >                                                    reply_to_map[i].fallback);\r
296 >  \r
297 > -     addr = add_recipients_for_string (reply, config,\r
298 > -                                       reply_to_map[i].recipient_type,\r
299 > -                                       recipients);\r
300 > +     addr = add_recipients_for_string (reply, config, recipient_type,\r
301 > +                                       recipients, add_recipients);\r
302 > +\r
303 >       if (from_addr == NULL)\r
304 >           from_addr = addr;\r
305 > +\r
306 > +     if (!reply_all) {\r
307 > +         /* Stop adding new recipients in reply-to-sender mode if we have\r
308 > +          * added some recipient(s) above.\r
309 > +          *\r
310 > +          * This also handles the case of user replying to his own message,\r
311 > +          * where reply-to/from is not a recipient. In this case there may be\r
312 > +          * more than one recipient even if not replying to all.\r
313 > +          */\r
314 > +         InternetAddressList *list;\r
315 > +         list = g_mime_message_get_recipients (reply, recipient_type);\r
316 > +         if (list && internet_address_list_length (list))\r
317 > +             add_recipients = FALSE;\r
318 \r
319 Is this different from just determining if add_recipients_for_string\r
320 added anything?  If not, maybe add_recipients_for_string (or\r
321 scan_address_list) could simply return whether or not it added any\r
322 recipients.\r
323 \r
324 > +\r
325 > +         /* Check if we've got a from address and all recipients we need. */\r
326 > +         if (!add_recipients && from_addr)\r
327 > +             break;\r
328 > +     }\r
329 >      }\r
330 >  \r
331 >      return from_addr;\r
332 > @@ -480,7 +508,8 @@ static int\r
333 >  notmuch_reply_format_default(void *ctx,\r
334 >                            notmuch_config_t *config,\r
335 >                            notmuch_query_t *query,\r
336 > -                          notmuch_show_params_t *params)\r
337 > +                          notmuch_show_params_t *params,\r
338 > +                          notmuch_bool_t reply_all)\r
339 >  {\r
340 >      GMimeMessage *reply;\r
341 >      notmuch_messages_t *messages;\r
342 > @@ -509,7 +538,8 @@ notmuch_reply_format_default(void *ctx,\r
343 >           g_mime_message_set_subject (reply, subject);\r
344 >       }\r
345 >  \r
346 > -     from_addr = add_recipients_from_message (reply, config, message);\r
347 > +     from_addr = add_recipients_from_message (reply, config, message,\r
348 > +                                              reply_all);\r
349 >  \r
350 >       if (from_addr == NULL)\r
351 >           from_addr = guess_from_received_header (config, message);\r
352 > @@ -558,7 +588,8 @@ static int\r
353 >  notmuch_reply_format_headers_only(void *ctx,\r
354 >                                 notmuch_config_t *config,\r
355 >                                 notmuch_query_t *query,\r
356 > -                               unused (notmuch_show_params_t *params))\r
357 > +                               unused (notmuch_show_params_t *params),\r
358 > +                               notmuch_bool_t reply_all)\r
359 >  {\r
360 >      GMimeMessage *reply;\r
361 >      notmuch_messages_t *messages;\r
362 > @@ -598,7 +629,7 @@ notmuch_reply_format_headers_only(void *ctx,\r
363 >       g_mime_object_set_header (GMIME_OBJECT (reply),\r
364 >                                 "References", references);\r
365 >  \r
366 > -     (void)add_recipients_from_message (reply, config, message);\r
367 > +     (void)add_recipients_from_message (reply, config, message, reply_all);\r
368 >  \r
369 >       reply_headers = g_mime_object_to_string (GMIME_OBJECT (reply));\r
370 >       printf ("%s", reply_headers);\r
371 > @@ -625,9 +656,10 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])\r
372 >      notmuch_query_t *query;\r
373 >      char *query_string;\r
374 >      int opt_index, ret = 0;\r
375 > -    int (*reply_format_func)(void *ctx, notmuch_config_t *config, notmuch_query_t *query, notmuch_show_params_t *params);\r
376 > +    int (*reply_format_func)(void *ctx, notmuch_config_t *config, notmuch_query_t *query, notmuch_show_params_t *params, notmuch_bool_t reply_all);\r
377 >      notmuch_show_params_t params = { .part = -1 };\r
378 >      int format = FORMAT_DEFAULT;\r
379 > +    int reply_all = TRUE;\r
380 >      notmuch_bool_t decrypt = FALSE;\r
381 >  \r
382 >      notmuch_opt_desc_t options[] = {\r
383 > @@ -635,6 +667,10 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])\r
384 >         (notmuch_keyword_t []){ { "default", FORMAT_DEFAULT },\r
385 >                                 { "headers-only", FORMAT_HEADERS_ONLY },\r
386 >                                 { 0, 0 } } },\r
387 > +     { NOTMUCH_OPT_KEYWORD, &reply_all, "reply-to", 'r',\r
388 > +       (notmuch_keyword_t []){ { "all", TRUE },\r
389 > +                               { "sender", FALSE },\r
390 > +                               { 0, 0 } } },\r
391 >       { NOTMUCH_OPT_BOOLEAN, &decrypt, "decrypt", 'd', 0 },\r
392 >       { 0, 0, 0, 0, 0 }\r
393 >      };\r
394 > @@ -688,7 +724,7 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])\r
395 >       return 1;\r
396 >      }\r
397 >  \r
398 > -    if (reply_format_func (ctx, config, query, &params) != 0)\r
399 > +    if (reply_format_func (ctx, config, query, &params, reply_all) != 0)\r
400 >       return 1;\r
401 >  \r
402 >      notmuch_query_destroy (query);\r