[notmuch] [PATCH] Allow saved queries for searching.

Jesse Rosenthal jrosenthal at jhu.edu
Tue Mar 23 12:48:22 PDT 2010


Add a "query:foo" term to the notmuch search syntax. Queries are "saved
searches", and are written in the config file:

[queries]
foo=from:jrosenthal and to:notmuchmail and queries
bar=tag:personal or (tag:unread and from:whomever)

Then, if you search with the query

`tag:inbox or query:foo'

it will be passed along to notmuch as

`tag:inbox and (from:jrosenthal and to:notmuchmail and queries)'.

At the moment, when you ask for a query that doesn't exist it just
treats it as blank. This seems more consistent than bailing out with an
error (since no other search term will do that, short of running out of
memory). This does mean, though, that non-existent queries, entered by
themselves, will lead to a blank-search-term error. It should be pretty
simple to improve this behavior, but I wanted to get the initial
functionality out there.

Note that this changed the arguments to query_string_from_args to include
the hash-table of saved queries -- and since a lot functions call that
one, this patch affects all of them. 
---
 notmuch-client.h      |   11 ++++++++---
 notmuch-config.c      |   38 ++++++++++++++++++++++++++++++++++++++
 notmuch-count.c       |    7 ++++++-
 notmuch-reply.c       |    7 ++++++-
 notmuch-search-tags.c |    7 ++++++-
 notmuch-search.c      |    8 +++++++-
 notmuch-show.c        |    7 ++++++-
 notmuch-tag.c         |   20 +++++++++++++-------
 query-string.c        |   21 +++++++++++++++++++--
 9 files changed, 109 insertions(+), 17 deletions(-)

diff --git a/notmuch-client.h b/notmuch-client.h
index c80b39c..daecbf4 100644
--- a/notmuch-client.h
+++ b/notmuch-client.h
@@ -116,9 +116,6 @@ notmuch_time_print_formatted_seconds (double seconds);
 double
 notmuch_time_elapsed (struct timeval start, struct timeval end);
 
-char *
-query_string_from_args (void *ctx, int argc, char *argv[]);
-
 notmuch_status_t
 show_message_body (const char *filename,
 		   void (*show_part) (GMimeObject *part, int *part_count));
@@ -135,6 +132,10 @@ notmuch_config_open (void *ctx,
 		     const char *filename,
 		     notmuch_bool_t *is_new_ret);
 
+char *
+query_string_from_args (void *ctx, GHashTable *queries_hash,
+			int argc, char *argv[]);
+
 void
 notmuch_config_close (notmuch_config_t *config);
 
@@ -162,6 +163,10 @@ void
 notmuch_config_set_user_primary_email (notmuch_config_t *config,
 				       const char *primary_email);
 
+void 
+notmuch_config_get_queries (notmuch_config_t *config, 
+			    GHashTable *queries_hash);
+
 char **
 notmuch_config_get_user_other_email (notmuch_config_t *config,
 				     size_t *length);
diff --git a/notmuch-config.c b/notmuch-config.c
index 95430db..ad81c25 100644
--- a/notmuch-config.c
+++ b/notmuch-config.c
@@ -62,6 +62,8 @@ struct _notmuch_config {
     char *user_primary_email;
     char **user_other_email;
     size_t user_other_email_length;
+    
+    GHashTable *queries_hash;
 };
 
 static int
@@ -70,6 +72,8 @@ notmuch_config_destructor (notmuch_config_t *config)
     if (config->key_file)
 	g_key_file_free (config->key_file);
 
+    g_hash_table_unref (config->queries_hash);
+
     return 0;
 }
 
@@ -200,6 +204,11 @@ notmuch_config_open (void *ctx,
     config->user_other_email = NULL;
     config->user_other_email_length = 0;
 
+    config->queries_hash =  g_hash_table_new_full (g_str_hash, 
+						   g_str_equal,
+						   free, 
+						   NULL);
+
     if (! g_key_file_load_from_file (config->key_file,
 				     config->filename,
 				     G_KEY_FILE_KEEP_COMMENTS,
@@ -264,6 +273,8 @@ notmuch_config_open (void *ctx,
 	}
     }
 
+    notmuch_config_get_queries (config, config->queries_hash);
+
     /* When we create a new configuration file here, we  add some
      * comments to help the user understand what can be done. */
     if (is_new) {
@@ -342,6 +353,33 @@ notmuch_config_get_database_path (notmuch_config_t *config)
     return config->database_path;
 }
 
+
+void
+notmuch_config_get_queries (notmuch_config_t *config,
+			    GHashTable *queries_hash)
+{
+    char **keys;
+    gsize size;
+    keys = g_key_file_get_keys (config->key_file,
+				"queries",
+				&size,
+				NULL);
+    gsize i;
+    for (i = 0; i < size; i++) {
+	char *value;
+	value = g_key_file_get_string (config->key_file,
+				       "queries", 
+				       keys[i], 
+				       NULL);
+
+	g_hash_table_insert (queries_hash,
+			     keys[i],
+			     value);
+    }
+}
+    
+
+
 void
 notmuch_config_set_database_path (notmuch_config_t *config,
 				  const char *database_path)
diff --git a/notmuch-count.c b/notmuch-count.c
index 77aa433..2e8463b 100644
--- a/notmuch-count.c
+++ b/notmuch-count.c
@@ -85,7 +85,12 @@ notmuch_count_command (void *ctx, int argc, char *argv[])
     if (notmuch == NULL)
 	return 1;
 
-    query_str = query_string_from_args (ctx, argc, argv);
+    GHashTable *queries_hash;
+    queries_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+    				    free, NULL);
+    notmuch_config_get_queries (config, queries_hash);
+
+    query_str = query_string_from_args (ctx, queries_hash, argc, argv);
     if (query_str == NULL) {
 	fprintf (stderr, "Out of memory.\n");
 	return 1;
diff --git a/notmuch-reply.c b/notmuch-reply.c
index 6c15536..5b10c68 100644
--- a/notmuch-reply.c
+++ b/notmuch-reply.c
@@ -456,7 +456,12 @@ notmuch_reply_command (void *ctx, int argc, char *argv[])
     if (config == NULL)
 	return 1;
 
-    query_string = query_string_from_args (ctx, argc, argv);
+    GHashTable *queries_hash;
+    queries_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+    				    free, NULL);
+    notmuch_config_get_queries (config, queries_hash);
+
+    query_string = query_string_from_args (ctx, queries_hash, argc, argv);
     if (query_string == NULL) {
 	fprintf (stderr, "Out of memory\n");
 	return 1;
diff --git a/notmuch-search-tags.c b/notmuch-search-tags.c
index 6f3cfcc..e021cc3 100644
--- a/notmuch-search-tags.c
+++ b/notmuch-search-tags.c
@@ -57,8 +57,13 @@ notmuch_search_tags_command (void *ctx, int argc, char *argv[])
 	goto error;
     }
 
+    GHashTable *queries_hash;
+    queries_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+    				    free, NULL);
+    notmuch_config_get_queries (config, queries_hash);
+
     if (argc > 0) {
-	if ((query_str = query_string_from_args (ctx, argc, argv)) == NULL) {
+	if ((query_str = query_string_from_args (ctx, queries_hash, argc, argv)) == NULL) {
 	    fprintf (stderr, "Out of memory.\n");
 	    goto error;
 	}
diff --git a/notmuch-search.c b/notmuch-search.c
index 4e3514b..a35838b 100644
--- a/notmuch-search.c
+++ b/notmuch-search.c
@@ -244,12 +244,18 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
     if (config == NULL)
 	return 1;
 
+    GHashTable *queries_hash;
+    queries_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+    				    free, NULL);
+    notmuch_config_get_queries (config, queries_hash);
+
     notmuch = notmuch_database_open (notmuch_config_get_database_path (config),
 				     NOTMUCH_DATABASE_MODE_READ_ONLY);
     if (notmuch == NULL)
 	return 1;
 
-    query_str = query_string_from_args (ctx, argc, argv);
+
+    query_str = query_string_from_args (ctx, queries_hash, argc, argv);
     if (query_str == NULL) {
 	fprintf (stderr, "Out of memory.\n");
 	return 1;
diff --git a/notmuch-show.c b/notmuch-show.c
index ff1fecb..f324ca3 100644
--- a/notmuch-show.c
+++ b/notmuch-show.c
@@ -446,7 +446,12 @@ notmuch_show_command (void *ctx, unused (int argc), unused (char *argv[]))
     if (config == NULL)
 	return 1;
 
-    query_string = query_string_from_args (ctx, argc, argv);
+    GHashTable *queries_hash;
+    queries_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+    				    free, NULL);
+    notmuch_config_get_queries (config, queries_hash);
+
+    query_string = query_string_from_args (ctx, queries_hash, argc, argv);
     if (query_string == NULL) {
 	fprintf (stderr, "Out of memory\n");
 	return 1;
diff --git a/notmuch-tag.c b/notmuch-tag.c
index 8b6f7dc..f65bb53 100644
--- a/notmuch-tag.c
+++ b/notmuch-tag.c
@@ -85,13 +85,6 @@ notmuch_tag_command (void *ctx, unused (int argc), unused (char *argv[]))
 	return 1;
     }
 
-    query_string = query_string_from_args (ctx, argc - i, &argv[i]);
-
-    if (*query_string == '\0') {
-	fprintf (stderr, "Error: notmuch tag requires at least one search term.\n");
-	return 1;
-    }
-
     config = notmuch_config_open (ctx, NULL, NULL);
     if (config == NULL)
 	return 1;
@@ -101,6 +94,19 @@ notmuch_tag_command (void *ctx, unused (int argc), unused (char *argv[]))
     if (notmuch == NULL)
 	return 1;
 
+    GHashTable *queries_hash;
+    queries_hash = g_hash_table_new_full (g_str_hash, g_str_equal,
+    				    free, NULL);
+    notmuch_config_get_queries (config, queries_hash);
+
+    query_string = query_string_from_args (ctx, queries_hash, argc - i, &argv[i]);
+
+    if (*query_string == '\0') {
+	fprintf (stderr, "Error: notmuch tag requires at least one search term.\n");
+	return 1;
+    }
+
+
     query = notmuch_query_create (notmuch, query_string);
     if (query == NULL) {
 	fprintf (stderr, "Out of memory.\n");
diff --git a/query-string.c b/query-string.c
index 6536512..2bd79c8 100644
--- a/query-string.c
+++ b/query-string.c
@@ -30,7 +30,8 @@
  * This function returns NULL in case of insufficient memory.
  */
 char *
-query_string_from_args (void *ctx, int argc, char *argv[])
+query_string_from_args (void *ctx, GHashTable *queries_hash,
+			int argc, char *argv[])
 {
     char *query_string;
     int i;
@@ -46,7 +47,23 @@ query_string_from_args (void *ctx, int argc, char *argv[])
 		return NULL;
 	}
 
-	query_string = talloc_strdup_append (query_string, argv[i]);
+	if (STRNCMP_LITERAL (argv[i], "query:") == 0) {
+
+	    char *saved_search;
+	    char  *replacement;
+	    char *replacement_string;
+
+	    saved_search = argv[i] + sizeof ("query:") - 1;
+	    
+	    replacement = g_hash_table_lookup (queries_hash, saved_search);
+	    replacement_string = talloc_asprintf (ctx, 
+						  "(%s)",
+						  (char *) replacement);
+
+	    query_string = talloc_strdup_append (query_string, replacement);
+	} else {
+	    query_string = talloc_strdup_append (query_string, argv[i]);
+	}
 	if (query_string == NULL)
 	    return NULL;
     }
-- 
1.6.3.3



More information about the notmuch mailing list