search: Support automatic tag exclusions

This adds a "search" section to the config file and an
"auto_tag_exclusions" setting in that section.  The search and count
commands pass tag tags from the configuration to the library.
This commit is contained in:
Austin Clements 2012-01-14 19:17:34 -05:00 committed by David Bremner
parent 3b76adf9e2
commit 42a9079928
5 changed files with 84 additions and 0 deletions

View file

@ -235,6 +235,14 @@ void
notmuch_config_set_maildir_synchronize_flags (notmuch_config_t *config, notmuch_config_set_maildir_synchronize_flags (notmuch_config_t *config,
notmuch_bool_t synchronize_flags); notmuch_bool_t synchronize_flags);
const char **
notmuch_config_get_auto_exclude_tags (notmuch_config_t *config, size_t *length);
void
notmuch_config_set_auto_exclude_tags (notmuch_config_t *config,
const char *list[],
size_t length);
int int
notmuch_run_hook (const char *db_path, const char *hook); notmuch_run_hook (const char *db_path, const char *hook);

View file

@ -84,6 +84,15 @@ static const char maildir_config_comment[] =
"\tand update tags, while the \"notmuch tag\" and \"notmuch restore\"\n" "\tand update tags, while the \"notmuch tag\" and \"notmuch restore\"\n"
"\tcommands will notice tag changes and update flags in filenames\n"; "\tcommands will notice tag changes and update flags in filenames\n";
static const char search_config_comment[] =
" Search configuration\n"
"\n"
" The following option is supported here:\n"
"\n"
"\tauto_exclude_tags A ;-separated list of tags that will be\n"
"\t excluded from search results by default. Using an excluded tag\n"
"\t in a query will override that exclusion.\n";
struct _notmuch_config { struct _notmuch_config {
char *filename; char *filename;
GKeyFile *key_file; GKeyFile *key_file;
@ -96,6 +105,8 @@ struct _notmuch_config {
const char **new_tags; const char **new_tags;
size_t new_tags_length; size_t new_tags_length;
notmuch_bool_t maildir_synchronize_flags; notmuch_bool_t maildir_synchronize_flags;
const char **auto_exclude_tags;
size_t auto_exclude_tags_length;
}; };
static int static int
@ -221,6 +232,7 @@ notmuch_config_open (void *ctx,
int file_had_new_group; int file_had_new_group;
int file_had_user_group; int file_had_user_group;
int file_had_maildir_group; int file_had_maildir_group;
int file_had_search_group;
if (is_new_ret) if (is_new_ret)
*is_new_ret = 0; *is_new_ret = 0;
@ -252,6 +264,8 @@ notmuch_config_open (void *ctx,
config->new_tags = NULL; config->new_tags = NULL;
config->new_tags_length = 0; config->new_tags_length = 0;
config->maildir_synchronize_flags = TRUE; config->maildir_synchronize_flags = TRUE;
config->auto_exclude_tags = NULL;
config->auto_exclude_tags_length = 0;
if (! g_key_file_load_from_file (config->key_file, if (! g_key_file_load_from_file (config->key_file,
config->filename, config->filename,
@ -295,6 +309,7 @@ notmuch_config_open (void *ctx,
file_had_new_group = g_key_file_has_group (config->key_file, "new"); file_had_new_group = g_key_file_has_group (config->key_file, "new");
file_had_user_group = g_key_file_has_group (config->key_file, "user"); file_had_user_group = g_key_file_has_group (config->key_file, "user");
file_had_maildir_group = g_key_file_has_group (config->key_file, "maildir"); file_had_maildir_group = g_key_file_has_group (config->key_file, "maildir");
file_had_search_group = g_key_file_has_group (config->key_file, "search");
if (notmuch_config_get_database_path (config) == NULL) { if (notmuch_config_get_database_path (config) == NULL) {
@ -345,6 +360,11 @@ notmuch_config_open (void *ctx,
notmuch_config_set_new_tags (config, tags, 2); notmuch_config_set_new_tags (config, tags, 2);
} }
if (notmuch_config_get_auto_exclude_tags (config, &tmp) == NULL) {
const char *tags[] = { "deleted", "spam" };
notmuch_config_set_auto_exclude_tags (config, tags, 2);
}
error = NULL; error = NULL;
config->maildir_synchronize_flags = config->maildir_synchronize_flags =
g_key_file_get_boolean (config->key_file, g_key_file_get_boolean (config->key_file,
@ -387,6 +407,11 @@ notmuch_config_open (void *ctx,
maildir_config_comment, NULL); maildir_config_comment, NULL);
} }
if (! file_had_search_group) {
g_key_file_set_comment (config->key_file, "search", NULL,
search_config_comment, NULL);
}
if (is_new_ret) if (is_new_ret)
*is_new_ret = is_new; *is_new_ret = is_new;
@ -597,6 +622,23 @@ notmuch_config_set_new_tags (notmuch_config_t *config,
&(config->new_tags)); &(config->new_tags));
} }
const char **
notmuch_config_get_auto_exclude_tags (notmuch_config_t *config, size_t *length)
{
return _config_get_list (config, "search", "auto_exclude_tags",
&(config->auto_exclude_tags),
&(config->auto_exclude_tags_length), length);
}
void
notmuch_config_set_auto_exclude_tags (notmuch_config_t *config,
const char *list[],
size_t length)
{
_config_set_list (config, "search", "auto_exclude_tags", list, length,
&(config->auto_exclude_tags));
}
/* Given a configuration item of the form <group>.<key> return the /* Given a configuration item of the form <group>.<key> return the
* component group and key. If any error occurs, print a message on * component group and key. If any error occurs, print a message on
* stderr and return 1. Otherwise, return 0. * stderr and return 1. Otherwise, return 0.

View file

@ -35,6 +35,9 @@ notmuch_count_command (void *ctx, int argc, char *argv[])
char *query_str; char *query_str;
int opt_index; int opt_index;
int output = OUTPUT_MESSAGES; int output = OUTPUT_MESSAGES;
const char **auto_exclude_tags;
size_t auto_exclude_tags_length;
unsigned int i;
notmuch_opt_desc_t options[] = { notmuch_opt_desc_t options[] = {
{ NOTMUCH_OPT_KEYWORD, &output, "output", 'o', { NOTMUCH_OPT_KEYWORD, &output, "output", 'o',
@ -75,6 +78,11 @@ notmuch_count_command (void *ctx, int argc, char *argv[])
return 1; return 1;
} }
auto_exclude_tags = notmuch_config_get_auto_exclude_tags
(config, &auto_exclude_tags_length);
for (i = 0; i < auto_exclude_tags_length; i++)
notmuch_query_add_tag_exclude (query, auto_exclude_tags[i]);
switch (output) { switch (output) {
case OUTPUT_MESSAGES: case OUTPUT_MESSAGES:
printf ("%u\n", notmuch_query_count_messages (query)); printf ("%u\n", notmuch_query_count_messages (query));

View file

@ -423,6 +423,9 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
output_t output = OUTPUT_SUMMARY; output_t output = OUTPUT_SUMMARY;
int offset = 0; int offset = 0;
int limit = -1; /* unlimited */ int limit = -1; /* unlimited */
const char **auto_exclude_tags;
size_t auto_exclude_tags_length;
unsigned int i;
enum { NOTMUCH_FORMAT_JSON, NOTMUCH_FORMAT_TEXT } enum { NOTMUCH_FORMAT_JSON, NOTMUCH_FORMAT_TEXT }
format_sel = NOTMUCH_FORMAT_TEXT; format_sel = NOTMUCH_FORMAT_TEXT;
@ -490,6 +493,11 @@ notmuch_search_command (void *ctx, int argc, char *argv[])
notmuch_query_set_sort (query, sort); notmuch_query_set_sort (query, sort);
auto_exclude_tags = notmuch_config_get_auto_exclude_tags
(config, &auto_exclude_tags_length);
for (i = 0; i < auto_exclude_tags_length; i++)
notmuch_query_add_tag_exclude (query, auto_exclude_tags[i]);
switch (output) { switch (output) {
default: default:
case OUTPUT_SUMMARY: case OUTPUT_SUMMARY:

View file

@ -129,4 +129,22 @@ add_message '[subject]="utf8-message-body-subject"' '[date]="Sat, 01 Jan 2000 12
output=$(notmuch search "bödý" | notmuch_search_sanitize) output=$(notmuch search "bödý" | notmuch_search_sanitize)
test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; utf8-message-body-subject (inbox unread)" test_expect_equal "$output" "thread:XXX 2000-01-01 [1/1] Notmuch Test Suite; utf8-message-body-subject (inbox unread)"
test_begin_subtest "Exclude \"deleted\" messages from search"
generate_message '[subject]="Not deleted"'
generate_message '[subject]="Deleted"'
notmuch new > /dev/null
notmuch tag +deleted id:$gen_msg_id
output=$(notmuch search subject:deleted | notmuch_search_sanitize)
test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread)"
test_begin_subtest "Exclude \"deleted\" messages from search, overridden"
output=$(notmuch search subject:deleted and tag:deleted | notmuch_search_sanitize)
test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Deleted (deleted inbox unread)"
test_begin_subtest "Exclude \"deleted\" messages from threads"
add_message '[subject]="Not deleted reply"' '[in-reply-to]="<$gen_msg_id>"'
output=$(notmuch search subject:deleted | notmuch_search_sanitize)
test_expect_equal "$output" "thread:XXX 2001-01-05 [1/1] Notmuch Test Suite; Not deleted (inbox unread)
thread:XXX 2001-01-05 [1/2] Notmuch Test Suite; Not deleted reply (deleted inbox unread)"
test_done test_done