Re: [PATCH] emacs: wash: make word-wrap bound message width
[notmuch-archives.git] / fd / 7a32ea31f7fc2ab5e8d2ba387c955898c36e3c
1 Return-Path: <dmitry.kurochkin@gmail.com>\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 71F5B429E27\r
6         for <notmuch@notmuchmail.org>; Mon,  7 Nov 2011 20:34:53 -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.799\r
10 X-Spam-Level: \r
11 X-Spam-Status: No, score=-0.799 tagged_above=-999 required=5\r
12         tests=[DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1,\r
13         FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_LOW=-0.7] 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 szeFB-HruJIX for <notmuch@notmuchmail.org>;\r
17         Mon,  7 Nov 2011 20:34:52 -0800 (PST)\r
18 Received: from mail-bw0-f53.google.com (mail-bw0-f53.google.com\r
19         [209.85.214.53]) (using TLSv1 with cipher RC4-SHA (128/128 bits))\r
20         (No client certificate requested)\r
21         by olra.theworths.org (Postfix) with ESMTPS id 4D065431FB6\r
22         for <notmuch@notmuchmail.org>; Mon,  7 Nov 2011 20:34:52 -0800 (PST)\r
23 Received: by bkaq10 with SMTP id q10so88250bka.26\r
24         for <notmuch@notmuchmail.org>; Mon, 07 Nov 2011 20:34:49 -0800 (PST)\r
25 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma;\r
26         h=from:to:subject:in-reply-to:references:user-agent:date:message-id\r
27         :mime-version:content-type;\r
28         bh=guJO5VtJYdYEu5Ut/R+jv3pK/W4WgiY4akkXkDp4hCA=;\r
29         b=Xq27+zSA9iOEiz4s/Se6LWSBAibdfEUH+F54YXGeiwxCY8v0Gvzli/aDzWVXPNi9gR\r
30         UHNmV2ZEmYCduxWYt0eqaJ9bjCyZcjzlhHRKlAxiOmzFuSz9Zj1/JtqX6QCOOqAD6vqH\r
31         WDkqx5Bhuda1FRRzVfuIlf/GjeUMgvPfrGw8I=\r
32 Received: by 10.204.9.205 with SMTP id m13mr21080663bkm.32.1320726884572;\r
33         Mon, 07 Nov 2011 20:34:44 -0800 (PST)\r
34 Received: from localhost ([91.144.186.21])\r
35         by mx.google.com with ESMTPS id z15sm233074bkv.4.2011.11.07.20.34.42\r
36         (version=TLSv1/SSLv3 cipher=OTHER);\r
37         Mon, 07 Nov 2011 20:34:43 -0800 (PST)\r
38 From: Dmitry Kurochkin <dmitry.kurochkin@gmail.com>\r
39 To: Austin Clements <amdragon@MIT.EDU>, notmuch@notmuchmail.org\r
40 Subject: Re: [PATCH] tag: Automatically limit to messages whose tags will\r
41         actually change.\r
42 In-Reply-To: <1320724523-23568-1-git-send-email-amdragon@mit.edu>\r
43 References: <1320724523-23568-1-git-send-email-amdragon@mit.edu>\r
44 User-Agent: Notmuch/0.9+34~g27fff04 (http://notmuchmail.org) Emacs/23.3.1\r
45         (x86_64-pc-linux-gnu)\r
46 Date: Tue, 08 Nov 2011 08:34:32 +0400\r
47 Message-ID: <878vnrut9j.fsf@gmail.com>\r
48 MIME-Version: 1.0\r
49 Content-Type: text/plain; charset=us-ascii\r
50 X-BeenThere: notmuch@notmuchmail.org\r
51 X-Mailman-Version: 2.1.13\r
52 Precedence: list\r
53 List-Id: "Use and development of the notmuch mail system."\r
54         <notmuch.notmuchmail.org>\r
55 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,\r
56         <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>\r
57 List-Archive: <http://notmuchmail.org/pipermail/notmuch>\r
58 List-Post: <mailto:notmuch@notmuchmail.org>\r
59 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>\r
60 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,\r
61         <mailto:notmuch-request@notmuchmail.org?subject=subscribe>\r
62 X-List-Received-Date: Tue, 08 Nov 2011 04:34:53 -0000\r
63 \r
64 Hi Austin.\r
65 \r
66 On Mon,  7 Nov 2011 22:55:23 -0500, Austin Clements <amdragon@MIT.EDU> wrote:\r
67 > This optimizes the user's tagging query to exclude messages that won't\r
68 > be affected by the tagging operation, saving computation and IO for\r
69 > redundant tagging operations.\r
70\r
71 > For example,\r
72 >   notmuch tag +notmuch to:notmuch@notmuchmail.org\r
73 > will now use the query\r
74 >   ( to:notmuch@notmuchmail.org ) and (not tag:"notmuch")\r
75\r
76 > In the past, we've often suggested that people do this exact\r
77 > transformation by hand for slow tagging operations.  This makes that\r
78 > unnecessary.\r
79 \r
80 Thanks!  This is a very useful optimization.\r
81 \r
82 Does it work for multiple tags and tag removal?  I.e.:\r
83 \r
84   notmuch tag -inbox -unread +sent from:dmitry.kurochkin@gmail.com\r
85 \r
86 can be converted to:\r
87 \r
88   notmuch tag -inbox -unread +sent from:dmitry.kurochkin@gmail.com and (tag:inbox or tag:unread or (not tag:sent))\r
89 \r
90 Regards,\r
91   Dmitry\r
92 \r
93 > ---\r
94 > I was about to implement this optimization in my initial tagging\r
95 > script, but then I figured, why not just do it in notmuch so we can\r
96 > stop telling people to do this by hand?\r
97\r
98 >  NEWS          |    9 ++++++\r
99 >  notmuch-tag.c |   76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++\r
100 >  2 files changed, 85 insertions(+), 0 deletions(-)\r
101\r
102 > diff --git a/NEWS b/NEWS\r
103 > index e00452a..9ca5e0c 100644\r
104 > --- a/NEWS\r
105 > +++ b/NEWS\r
106 > @@ -16,6 +16,15 @@ Add search terms to  "notmuch dump"\r
107 >    search/show/tag. The output file argument of dump is deprecated in\r
108 >    favour of using stdout.\r
109 >  \r
110 > +Optimizations\r
111 > +-------------\r
112 > +\r
113 > +Automatic tag query optimization\r
114 > +\r
115 > +  "notmuch tag" now automatically optimizes the user's query to\r
116 > +  exclude messages whose tags won't change.  In the past, we've\r
117 > +  suggested that people do this by hand; this is no longer necessary.\r
118 > +\r
119 >  Notmuch 0.9 (2011-10-01)\r
120 >  ========================\r
121 >  \r
122 > diff --git a/notmuch-tag.c b/notmuch-tag.c\r
123 > index dded39e..62c4bf1 100644\r
124 > --- a/notmuch-tag.c\r
125 > +++ b/notmuch-tag.c\r
126 > @@ -30,6 +30,76 @@ handle_sigint (unused (int sig))\r
127 >      interrupted = 1;\r
128 >  }\r
129 >  \r
130 > +static char *\r
131 > +_escape_tag (char *buf, const char *tag)\r
132 > +{\r
133 > +    const char *in = tag;\r
134 > +    char *out = buf;\r
135 > +    /* Boolean terms surrounded by double quotes can contain any\r
136 > +     * character.  Double quotes are quoted by doubling them. */\r
137 > +    *(out++) = '"';\r
138 > +    while (*in) {\r
139 > +     if (*in == '"')\r
140 > +         *(out++) = '"';\r
141 > +     *(out++) = *(in++);\r
142 > +    }\r
143 > +    *(out++) = '"';\r
144 > +    *out = 0;\r
145 > +    return buf;\r
146 > +}\r
147 > +\r
148 > +static char *\r
149 > +_optimize_tag_query (void *ctx, const char *orig_query_string, char *argv[],\r
150 > +                  int *add_tags, int add_tags_count,\r
151 > +                  int *remove_tags, int remove_tags_count)\r
152 > +{\r
153 > +    /* This is subtler than it looks.  Xapian ignores the '-' operator\r
154 > +     * at the beginning both queries and parenthesized groups and,\r
155 > +     * furthermore, the presence of a '-' operator at the beginning of\r
156 > +     * a group can inhibit parsing of the previous operator.  Hence,\r
157 > +     * the user-provided query MUST appear first, but it is safe to\r
158 > +     * parenthesize and the exclusion part of the query must not use\r
159 > +     * the '-' operator (though the NOT operator is fine). */\r
160 > +\r
161 > +    char *escaped, *query_string;\r
162 > +    const char *join = "";\r
163 > +    int i;\r
164 > +    unsigned int max_tag_len = 0;\r
165 > +\r
166 > +    /* Allocate a buffer for escaping tags. */\r
167 > +    for (i = 0; i < add_tags_count; i++)\r
168 > +     if (strlen (argv[add_tags[i]] + 1) > max_tag_len)\r
169 > +         max_tag_len = strlen (argv[add_tags[i]] + 1);\r
170 > +    for (i = 0; i < remove_tags_count; i++)\r
171 > +     if (strlen (argv[remove_tags[i]] + 1) > max_tag_len)\r
172 > +         max_tag_len = strlen (argv[remove_tags[i]] + 1);\r
173 > +    escaped = talloc_array(ctx, char, max_tag_len * 2 + 3);\r
174 > +\r
175 > +    /* Build the new query string */\r
176 > +    if (strcmp (orig_query_string, "*") == 0)\r
177 > +     query_string = talloc_strdup (ctx, "(");\r
178 > +    else\r
179 > +     query_string = talloc_asprintf (ctx, "( %s ) and (", orig_query_string);\r
180 > +\r
181 > +    for (i = 0; i < add_tags_count; i++) {\r
182 > +     query_string = talloc_asprintf_append_buffer (\r
183 > +         query_string, "%snot tag:%s", join,\r
184 > +         _escape_tag (escaped, argv[add_tags[i]] + 1));\r
185 > +     join = " or ";\r
186 > +    }\r
187 > +    for (i = 0; i < remove_tags_count; i++) {\r
188 > +     query_string = talloc_asprintf_append_buffer (\r
189 > +         query_string, "%stag:%s", join,\r
190 > +         _escape_tag (escaped, argv[remove_tags[i]] + 1));\r
191 > +     join = " or ";\r
192 > +    }\r
193 > +\r
194 > +    query_string = talloc_strdup_append_buffer (query_string, ")");\r
195 > +\r
196 > +    talloc_free (escaped);\r
197 > +    return query_string;\r
198 > +}\r
199 > +\r
200 >  int\r
201 >  notmuch_tag_command (void *ctx, unused (int argc), unused (char *argv[]))\r
202 >  {\r
203 > @@ -93,6 +163,12 @@ notmuch_tag_command (void *ctx, unused (int argc), unused (char *argv[]))\r
204 >       return 1;\r
205 >      }\r
206 >  \r
207 > +    /* Optimize the query so it excludes messages that already have\r
208 > +     * the specified set of tags. */\r
209 > +    query_string = _optimize_tag_query (ctx, query_string, argv,\r
210 > +                                     add_tags, add_tags_count,\r
211 > +                                     remove_tags, remove_tags_count);\r
212 > +\r
213 >      config = notmuch_config_open (ctx, NULL, NULL);\r
214 >      if (config == NULL)\r
215 >       return 1;\r
216 > -- \r
217 > 1.7.7.1\r
218\r
219 > _______________________________________________\r
220 > notmuch mailing list\r
221 > notmuch@notmuchmail.org\r
222 > http://notmuchmail.org/mailman/listinfo/notmuch\r