1 Return-Path: <prvs=jrosenthal=691fa5400@jhu.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 B203F4196F0
\r
6 for <notmuch@notmuchmail.org>; Tue, 23 Mar 2010 12:48:17 -0700 (PDT)
\r
7 X-Virus-Scanned: Debian amavisd-new at olra.theworths.org
\r
11 X-Spam-Status: No, score=-2.8 tagged_above=-999 required=5
\r
12 tests=[BAYES_05=-0.5, RCVD_IN_DNSWL_MED=-2.3] autolearn=ham
\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 0stSLAseDfei for <notmuch@notmuchmail.org>;
\r
16 Tue, 23 Mar 2010 12:48:15 -0700 (PDT)
\r
17 Received: from ipex2.johnshopkins.edu (ipex2.johnshopkins.edu [162.129.8.151])
\r
18 by olra.theworths.org (Postfix) with ESMTP id E6BE4431FC1
\r
19 for <notmuch@notmuchmail.org>; Tue, 23 Mar 2010 12:48:14 -0700 (PDT)
\r
20 X-IronPort-AV: E=Sophos;i="4.51,296,1267419600"; d="scan'208";a="315237919"
\r
21 Received: from c-69-255-36-229.hsd1.md.comcast.net (HELO lucky)
\r
23 by ipex2.johnshopkins.edu with ESMTP/TLS/AES256-SHA;
\r
24 23 Mar 2010 15:48:14 -0400
\r
25 Received: from jkr by lucky with local (Exim 4.69)
\r
26 (envelope-from <jrosenthal@jhu.edu>)
\r
27 id 1NuA5O-0004g0-6O; Tue, 23 Mar 2010 15:48:22 -0400
\r
28 From: Jesse Rosenthal <jrosenthal@jhu.edu>
\r
29 To: notmuch@notmuchmail.org
\r
30 Date: Tue, 23 Mar 2010 15:48:22 -0400
\r
31 Message-ID: <87d3yulszd.fsf@jhu.edu>
\r
33 Content-Type: text/plain; charset=us-ascii
\r
34 Subject: [notmuch] [PATCH] Allow saved queries for searching.
\r
35 X-BeenThere: notmuch@notmuchmail.org
\r
36 X-Mailman-Version: 2.1.13
\r
38 List-Id: "Use and development of the notmuch mail system."
\r
39 <notmuch.notmuchmail.org>
\r
40 List-Unsubscribe: <http://notmuchmail.org/mailman/options/notmuch>,
\r
41 <mailto:notmuch-request@notmuchmail.org?subject=unsubscribe>
\r
42 List-Archive: <http://notmuchmail.org/pipermail/notmuch>
\r
43 List-Post: <mailto:notmuch@notmuchmail.org>
\r
44 List-Help: <mailto:notmuch-request@notmuchmail.org?subject=help>
\r
45 List-Subscribe: <http://notmuchmail.org/mailman/listinfo/notmuch>,
\r
46 <mailto:notmuch-request@notmuchmail.org?subject=subscribe>
\r
47 X-List-Received-Date: Tue, 23 Mar 2010 19:48:17 -0000
\r
49 Add a "query:foo" term to the notmuch search syntax. Queries are "saved
\r
50 searches", and are written in the config file:
\r
53 foo=from:jrosenthal and to:notmuchmail and queries
\r
54 bar=tag:personal or (tag:unread and from:whomever)
\r
56 Then, if you search with the query
\r
58 `tag:inbox or query:foo'
\r
60 it will be passed along to notmuch as
\r
62 `tag:inbox and (from:jrosenthal and to:notmuchmail and queries)'.
\r
64 At the moment, when you ask for a query that doesn't exist it just
\r
65 treats it as blank. This seems more consistent than bailing out with an
\r
66 error (since no other search term will do that, short of running out of
\r
67 memory). This does mean, though, that non-existent queries, entered by
\r
68 themselves, will lead to a blank-search-term error. It should be pretty
\r
69 simple to improve this behavior, but I wanted to get the initial
\r
70 functionality out there.
\r
72 Note that this changed the arguments to query_string_from_args to include
\r
73 the hash-table of saved queries -- and since a lot functions call that
\r
74 one, this patch affects all of them.
\r
76 notmuch-client.h | 11 ++++++++---
\r
77 notmuch-config.c | 38 ++++++++++++++++++++++++++++++++++++++
\r
78 notmuch-count.c | 7 ++++++-
\r
79 notmuch-reply.c | 7 ++++++-
\r
80 notmuch-search-tags.c | 7 ++++++-
\r
81 notmuch-search.c | 8 +++++++-
\r
82 notmuch-show.c | 7 ++++++-
\r
83 notmuch-tag.c | 20 +++++++++++++-------
\r
84 query-string.c | 21 +++++++++++++++++++--
\r
85 9 files changed, 109 insertions(+), 17 deletions(-)
\r
87 diff --git a/notmuch-client.h b/notmuch-client.h
\r
88 index c80b39c..daecbf4 100644
\r
89 --- a/notmuch-client.h
\r
90 +++ b/notmuch-client.h
\r
91 @@ -116,9 +116,6 @@ notmuch_time_print_formatted_seconds (double seconds);
\r
93 notmuch_time_elapsed (struct timeval start, struct timeval end);
\r
96 -query_string_from_args (void *ctx, int argc, char *argv[]);
\r
99 show_message_body (const char *filename,
\r
100 void (*show_part) (GMimeObject *part, int *part_count));
\r
101 @@ -135,6 +132,10 @@ notmuch_config_open (void *ctx,
\r
102 const char *filename,
\r
103 notmuch_bool_t *is_new_ret);
\r
106 +query_string_from_args (void *ctx, GHashTable *queries_hash,
\r
107 + int argc, char *argv[]);
\r
110 notmuch_config_close (notmuch_config_t *config);
\r
112 @@ -162,6 +163,10 @@ void
\r
113 notmuch_config_set_user_primary_email (notmuch_config_t *config,
\r
114 const char *primary_email);
\r
117 +notmuch_config_get_queries (notmuch_config_t *config,
\r
118 + GHashTable *queries_hash);
\r
121 notmuch_config_get_user_other_email (notmuch_config_t *config,
\r
123 diff --git a/notmuch-config.c b/notmuch-config.c
\r
124 index 95430db..ad81c25 100644
\r
125 --- a/notmuch-config.c
\r
126 +++ b/notmuch-config.c
\r
127 @@ -62,6 +62,8 @@ struct _notmuch_config {
\r
128 char *user_primary_email;
\r
129 char **user_other_email;
\r
130 size_t user_other_email_length;
\r
132 + GHashTable *queries_hash;
\r
136 @@ -70,6 +72,8 @@ notmuch_config_destructor (notmuch_config_t *config)
\r
137 if (config->key_file)
\r
138 g_key_file_free (config->key_file);
\r
140 + g_hash_table_unref (config->queries_hash);
\r
145 @@ -200,6 +204,11 @@ notmuch_config_open (void *ctx,
\r
146 config->user_other_email = NULL;
\r
147 config->user_other_email_length = 0;
\r
149 + config->queries_hash = g_hash_table_new_full (g_str_hash,
\r
154 if (! g_key_file_load_from_file (config->key_file,
\r
156 G_KEY_FILE_KEEP_COMMENTS,
\r
157 @@ -264,6 +273,8 @@ notmuch_config_open (void *ctx,
\r
161 + notmuch_config_get_queries (config, config->queries_hash);
\r
163 /* When we create a new configuration file here, we add some
\r
164 * comments to help the user understand what can be done. */
\r
166 @@ -342,6 +353,33 @@ notmuch_config_get_database_path (notmuch_config_t *config)
\r
167 return config->database_path;
\r
172 +notmuch_config_get_queries (notmuch_config_t *config,
\r
173 + GHashTable *queries_hash)
\r
177 + keys = g_key_file_get_keys (config->key_file,
\r
182 + for (i = 0; i < size; i++) {
\r
184 + value = g_key_file_get_string (config->key_file,
\r
189 + g_hash_table_insert (queries_hash,
\r
198 notmuch_config_set_database_path (notmuch_config_t *config,
\r
199 const char *database_path)
\r
200 diff --git a/notmuch-count.c b/notmuch-count.c
\r
201 index 77aa433..2e8463b 100644
\r
202 --- a/notmuch-count.c
\r
203 +++ b/notmuch-count.c
\r
204 @@ -85,7 +85,12 @@ notmuch_count_command (void *ctx, int argc, char *argv[])
\r
205 if (notmuch == NULL)
\r
208 - query_str = query_string_from_args (ctx, argc, argv);
\r
209 + GHashTable *queries_hash;
\r
210 + queries_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
\r
212 + notmuch_config_get_queries (config, queries_hash);
\r
214 + query_str = query_string_from_args (ctx, queries_hash, argc, argv);
\r
215 if (query_str == NULL) {
\r
216 fprintf (stderr, "Out of memory.\n");
\r
218 diff --git a/notmuch-reply.c b/notmuch-reply.c
\r
219 index 6c15536..5b10c68 100644
\r
220 --- a/notmuch-reply.c
\r
221 +++ b/notmuch-reply.c
\r
222 @@ -456,7 +456,12 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])
\r
223 if (config == NULL)
\r
226 - query_string = query_string_from_args (ctx, argc, argv);
\r
227 + GHashTable *queries_hash;
\r
228 + queries_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
\r
230 + notmuch_config_get_queries (config, queries_hash);
\r
232 + query_string = query_string_from_args (ctx, queries_hash, argc, argv);
\r
233 if (query_string == NULL) {
\r
234 fprintf (stderr, "Out of memory\n");
\r
236 diff --git a/notmuch-search-tags.c b/notmuch-search-tags.c
\r
237 index 6f3cfcc..e021cc3 100644
\r
238 --- a/notmuch-search-tags.c
\r
239 +++ b/notmuch-search-tags.c
\r
240 @@ -57,8 +57,13 @@ notmuch_search_tags_command (void *ctx, int argc, char *argv[])
\r
244 + GHashTable *queries_hash;
\r
245 + queries_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
\r
247 + notmuch_config_get_queries (config, queries_hash);
\r
250 - if ((query_str = query_string_from_args (ctx, argc, argv)) == NULL) {
\r
251 + if ((query_str = query_string_from_args (ctx, queries_hash, argc, argv)) == NULL) {
\r
252 fprintf (stderr, "Out of memory.\n");
\r
255 diff --git a/notmuch-search.c b/notmuch-search.c
\r
256 index 4e3514b..a35838b 100644
\r
257 --- a/notmuch-search.c
\r
258 +++ b/notmuch-search.c
\r
259 @@ -244,12 +244,18 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
\r
260 if (config == NULL)
\r
263 + GHashTable *queries_hash;
\r
264 + queries_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
\r
266 + notmuch_config_get_queries (config, queries_hash);
\r
268 notmuch = notmuch_database_open (notmuch_config_get_database_path (config),
\r
269 NOTMUCH_DATABASE_MODE_READ_ONLY);
\r
270 if (notmuch == NULL)
\r
273 - query_str = query_string_from_args (ctx, argc, argv);
\r
275 + query_str = query_string_from_args (ctx, queries_hash, argc, argv);
\r
276 if (query_str == NULL) {
\r
277 fprintf (stderr, "Out of memory.\n");
\r
279 diff --git a/notmuch-show.c b/notmuch-show.c
\r
280 index ff1fecb..f324ca3 100644
\r
281 --- a/notmuch-show.c
\r
282 +++ b/notmuch-show.c
\r
283 @@ -446,7 +446,12 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
\r
284 if (config == NULL)
\r
287 - query_string = query_string_from_args (ctx, argc, argv);
\r
288 + GHashTable *queries_hash;
\r
289 + queries_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
\r
291 + notmuch_config_get_queries (config, queries_hash);
\r
293 + query_string = query_string_from_args (ctx, queries_hash, argc, argv);
\r
294 if (query_string == NULL) {
\r
295 fprintf (stderr, "Out of memory\n");
\r
297 diff --git a/notmuch-tag.c b/notmuch-tag.c
\r
298 index 8b6f7dc..f65bb53 100644
\r
299 --- a/notmuch-tag.c
\r
300 +++ b/notmuch-tag.c
\r
301 @@ -85,13 +85,6 @@ notmuch_tag_command (void *ctx, unused (int argc), unused (char *argv[]))
\r
305 - query_string = query_string_from_args (ctx, argc - i, &argv[i]);
\r
307 - if (*query_string == '\0') {
\r
308 - fprintf (stderr, "Error: notmuch tag requires at least one search term.\n");
\r
312 config = notmuch_config_open (ctx, NULL, NULL);
\r
313 if (config == NULL)
\r
315 @@ -101,6 +94,19 @@ notmuch_tag_command (void *ctx, unused (int argc), unused (char *argv[]))
\r
316 if (notmuch == NULL)
\r
319 + GHashTable *queries_hash;
\r
320 + queries_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
\r
322 + notmuch_config_get_queries (config, queries_hash);
\r
324 + query_string = query_string_from_args (ctx, queries_hash, argc - i, &argv[i]);
\r
326 + if (*query_string == '\0') {
\r
327 + fprintf (stderr, "Error: notmuch tag requires at least one search term.\n");
\r
332 query = notmuch_query_create (notmuch, query_string);
\r
333 if (query == NULL) {
\r
334 fprintf (stderr, "Out of memory.\n");
\r
335 diff --git a/query-string.c b/query-string.c
\r
336 index 6536512..2bd79c8 100644
\r
337 --- a/query-string.c
\r
338 +++ b/query-string.c
\r
340 * This function returns NULL in case of insufficient memory.
\r
343 -query_string_from_args (void *ctx, int argc, char *argv[])
\r
344 +query_string_from_args (void *ctx, GHashTable *queries_hash,
\r
345 + int argc, char *argv[])
\r
347 char *query_string;
\r
349 @@ -46,7 +47,23 @@ query_string_from_args (void *ctx, int argc, char *argv[])
\r
353 - query_string = talloc_strdup_append (query_string, argv[i]);
\r
354 + if (STRNCMP_LITERAL (argv[i], "query:") == 0) {
\r
356 + char *saved_search;
\r
357 + char *replacement;
\r
358 + char *replacement_string;
\r
360 + saved_search = argv[i] + sizeof ("query:") - 1;
\r
362 + replacement = g_hash_table_lookup (queries_hash, saved_search);
\r
363 + replacement_string = talloc_asprintf (ctx,
\r
365 + (char *) replacement);
\r
367 + query_string = talloc_strdup_append (query_string, replacement);
\r
369 + query_string = talloc_strdup_append (query_string, argv[i]);
\r
371 if (query_string == NULL)
\r