[PATCH] Fix notmuch-describe-key
Fix notmuch-describe-key crashing for the following two cases 1. format-kbd-macro cannot deal with keys like [(32 . 126)], switch to use key-description instead. 2. if a function in the current keymap is not bounded, it will crash the whole process. We check if it is bounded and silently skip it to avoid crashing. --- emacs/notmuch-lib.el | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/emacs/notmuch-lib.el b/emacs/notmuch-lib.el index 8cf7261e..546ab6fd 100644 --- a/emacs/notmuch-lib.el +++ b/emacs/notmuch-lib.el @@ -298,7 +298,7 @@ This is basically just `format-kbd-macro' but we also convert ESC to M-." "Prepend cons cells describing prefix-arg ACTUAL-KEY and ACTUAL-KEY to TAIL It does not prepend if ACTUAL-KEY is already listed in TAIL." - (let ((key-string (concat prefix (format-kbd-macro actual-key + (let ((key-string (concat prefix (key-description actual-key ;; We don't include documentation if the key-binding is ;; over-ridden. Note, over-riding a binding automatically hides the ;; prefixed version too. @@ -313,7 +313,7 @@ It does not prepend if ACTUAL-KEY is already listed in TAIL." ;; Documentation for command (push (cons key-string (or (and (symbolp binding) (get binding 'notmuch-doc)) - (notmuch-documentation-first-line binding))) + (and (functionp binding) (notmuch-documentation-first-line binding tail))) tail) -- 2.20.1 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: Reply to content of "List-Post" header?
Hi Ralph, * Ralph Seichter [2019-03-02; 17:34]: > * Brian Sniffen: > >> You can set message-subscribed-addresses or its cousins; then >> message-to-list-only will work for you. > > Ah, that's what was missing, thank you. indeed, I forgot: my procmmail scripts recognize mailing list headers and in the end there is a list of all mailing lists I ever got mails from and this list is referenced in message-subscribed-address-file. So I pretend beeing subscribed to all these lists which is not true but helps. Ciao; Gregor -- -... --- .-. . -.. ..--.. ...-.- ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] util: make remaining headers includable from C++
libnotmuch_util.a is supposed to be usable from the library and the CLI, but much the library is compiled as C++. Add in appropriate wrapping to prevent symbol mangling. These wrappers already existed in string-util.h; it seems better to be consistent. --- util/crypto.h | 7 +++ util/error_util.h | 7 +++ util/gmime-extra.h | 12 +--- util/hex-escape.h | 9 + util/talloc-extra.h | 8 util/xutil.h| 8 util/zlib-extra.h | 9 + 7 files changed, 57 insertions(+), 3 deletions(-) diff --git a/util/crypto.h b/util/crypto.h index c384601c..1a90f0e0 100644 --- a/util/crypto.h +++ b/util/crypto.h @@ -5,6 +5,10 @@ #include "gmime-extra.h" #include "notmuch.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct _notmuch_crypto { bool verify; notmuch_decryption_policy_t decrypt; @@ -34,4 +38,7 @@ _notmuch_crypto_get_gmime_ctx_for_protocol (_notmuch_crypto_t *crypto, void _notmuch_crypto_cleanup (_notmuch_crypto_t *crypto); +#ifdef __cplusplus +} +#endif #endif diff --git a/util/error_util.h b/util/error_util.h index 4bb338a2..aa3b77c4 100644 --- a/util/error_util.h +++ b/util/error_util.h @@ -25,6 +25,10 @@ #include "function-attributes.h" +#ifdef __cplusplus +extern "C" { +#endif + /* There's no point in continuing when we've detected that we've done * something wrong internally (as opposed to the user passing in a * bogus value). @@ -44,4 +48,7 @@ _internal_error (const char *format, ...) PRINTF_ATTRIBUTE (1, 2) NORETURN_ATTRI _internal_error (format " (%s).\n",\ ##__VA_ARGS__, __location__) +#ifdef __cplusplus +} +#endif #endif diff --git a/util/gmime-extra.h b/util/gmime-extra.h index ca822b8c..5d8c52f7 100644 --- a/util/gmime-extra.h +++ b/util/gmime-extra.h @@ -1,11 +1,13 @@ #ifndef _GMIME_EXTRA_H #define _GMIME_EXTRA_H #include - -GMimeStream *g_mime_stream_stdout_new(void); - #include +#ifdef __cplusplus +extern "C" { +#endif + +GMimeStream *g_mime_stream_stdout_new(void); #if (GMIME_MAJOR_VERSION < 3) @@ -100,4 +102,8 @@ gint64 g_mime_utils_header_decode_date_unix (const char *date); */ const char * g_mime_certificate_get_valid_userid (GMimeCertificate *cert); +#ifdef __cplusplus +} +#endif + #endif diff --git a/util/hex-escape.h b/util/hex-escape.h index 5182042e..50d946ed 100644 --- a/util/hex-escape.h +++ b/util/hex-escape.h @@ -1,6 +1,10 @@ #ifndef _HEX_ESCAPE_H #define _HEX_ESCAPE_H +#ifdef __cplusplus +extern "C" { +#endif + typedef enum hex_status { HEX_SUCCESS = 0, HEX_SYNTAX_ERROR, @@ -38,4 +42,9 @@ hex_decode (void *talloc_ctx, const char *in, char **out, */ hex_status_t hex_decode_inplace (char *s); + +#ifdef __cplusplus +} +#endif + #endif diff --git a/util/talloc-extra.h b/util/talloc-extra.h index eac5dc05..e2e61734 100644 --- a/util/talloc-extra.h +++ b/util/talloc-extra.h @@ -3,6 +3,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /* Like talloc_strndup, but take an extra parameter for the internal talloc * name (for debugging) */ @@ -15,4 +19,8 @@ talloc_strndup_named_const (void *ctx, const char *str, #define talloc_strndup_debug(ctx, str, len) talloc_strndup_named_const (ctx, str, len, __location__) +#ifdef __cplusplus +} +#endif + #endif diff --git a/util/xutil.h b/util/xutil.h index 4829f33c..e2707000 100644 --- a/util/xutil.h +++ b/util/xutil.h @@ -25,6 +25,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /* xutil.c */ void * xcalloc (size_t nmemb, size_t size); @@ -49,4 +53,8 @@ int xregexec (const regex_t *preg, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags); +#ifdef __cplusplus +} +#endif + #endif diff --git a/util/zlib-extra.h b/util/zlib-extra.h index aedfd48f..209fa998 100644 --- a/util/zlib-extra.h +++ b/util/zlib-extra.h @@ -4,6 +4,10 @@ #include "util.h" #include +#ifdef __cplusplus +extern "C" { +#endif + /* Like getline, but read from a gzFile. Allocation is with talloc. * Returns: * @@ -22,4 +26,9 @@ gz_getline (void *ctx, char **lineptr, ssize_t *bytes_read, gzFile stream); const char * gz_error_string (util_status_t status, gzFile stream); + +#ifdef __cplusplus +} +#endif + #endif -- 2.20.1 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH] lib/string_map: fix return type of string_cmp
I can't figure out how checking the sign of a bool ever worked. The following program demonstrates the problem (i.e. for me it prints 1). #include #include int main(int argc, char **argv) { bool x; x = -1; printf("x = %d\n", x); } This seems to be mandated by the C99 standard 6.3.1.2. --- I'd like to get this in a new point release ASAP. lib/string-map.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/string-map.c b/lib/string-map.c index ad818207..a88404c7 100644 --- a/lib/string-map.c +++ b/lib/string-map.c @@ -106,7 +106,7 @@ _notmuch_string_map_sort (notmuch_string_map_t *map) map->sorted = true; } -static bool +static int string_cmp (const char *a, const char *b, bool exact) { if (exact) -- 2.20.1 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: Reply to content of "List-Post" header?
* Brian Sniffen: > You can set message-subscribed-addresses or its cousins; then > message-to-list-only will work for you. Ah, that's what was missing, thank you. -Ralph ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: WIP2: index user headers
David Bremner writes: > This obsoletes [1] > This is getting closer to mergable, but it still needs at least to > sanity check the names of user defined prefixes (see point (a) below). > > The main differences from [1] are [1] is of course id:20181117140901.1870-1-da...@tethera.net > > (a) xapian prefixes are no longer defined via upper casing, as this is > locale dependent. The do rely on a ":" separator, hence the need > for some sanitization. > > (b) The caching of user header/prefix information is now done via > string maps, and used more effectively during indexing. > ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 1/7] cli/config: refactor _stored_in_db
This will make it easier to add other prefixes that are stored in the database, compared to special casing each one as "query." was. --- notmuch-config.c | 21 +++-- 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/notmuch-config.c b/notmuch-config.c index bf77cc9d..1517d0ff 100644 --- a/notmuch-config.c +++ b/notmuch-config.c @@ -821,17 +821,26 @@ _item_split (char *item, char **group, char **key) #define BUILT_WITH_PREFIX "built_with." +struct config_key { +const char *name; +bool prefix; +}; + static bool _stored_in_db (const char *item) { -const char * db_configs[] = { - "index.decrypt", +struct config_key db_configs[] = { + {"index.decrypt", false}, + {"query.", true}, }; -if (STRNCMP_LITERAL (item, "query.") == 0) - return true; -for (size_t i = 0; i < ARRAY_SIZE (db_configs); i++) - if (strcmp (item, db_configs[i]) == 0) +for (size_t i = 0; i < ARRAY_SIZE (db_configs); i++) { + if (db_configs[i].prefix && + strncmp (item, db_configs[i].name, +strlen(db_configs[i].name)) == 0) return true; + if (strcmp (item, db_configs[i].name) == 0) + return true; +} return false; } -- 2.20.1 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 3/7] lib: setup user headers in query parser
These tests will need to be updated if the Xapian query print/debug format changes. --- lib/database.cc | 35 +++ test/T730-user-header.sh | 21 + 2 files changed, 56 insertions(+) diff --git a/lib/database.cc b/lib/database.cc index 9cf8062c..4de79f79 100644 --- a/lib/database.cc +++ b/lib/database.cc @@ -299,6 +299,8 @@ prefix_t prefix_table[] = { NOTMUCH_FIELD_PROCESSOR}, }; +#define CONFIG_HEADER_PREFIX "index.header." + static void _setup_query_field_default (const prefix_t *prefix, notmuch_database_t *notmuch) { @@ -308,6 +310,38 @@ _setup_query_field_default (const prefix_t *prefix, notmuch_database_t *notmuch) notmuch->query_parser->add_boolean_prefix (prefix->name, prefix->prefix); } +static notmuch_status_t +_setup_user_query_fields (notmuch_database_t *notmuch) +{ +notmuch_config_list_t *list; +notmuch_status_t status; + +status = notmuch_database_get_config_list (notmuch, CONFIG_HEADER_PREFIX, ); +if (status) + return status; +for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) { + + prefix_t query_field { .name = NULL, .prefix = NULL, + .flags = NOTMUCH_FIELD_PROBABILISTIC | +NOTMUCH_FIELD_EXTERNAL + }; + + const char *key = notmuch_config_list_key (list) + + sizeof (CONFIG_HEADER_PREFIX) - 1; + + char *prefix = talloc_asprintf(notmuch, "XU%s:", key); + + query_field.name = key; + query_field.prefix = prefix; + + _setup_query_field_default (_field, notmuch); +} + +notmuch_config_list_destroy (list); + +return NOTMUCH_STATUS_SUCCESS; +} + #if HAVE_XAPIAN_FIELD_PROCESSOR static void _setup_query_field (const prefix_t *prefix, notmuch_database_t *notmuch) @@ -965,6 +999,7 @@ notmuch_database_open_verbose (const char *path, _setup_query_field (prefix, notmuch); } } + status = _setup_user_query_fields (notmuch); } catch (const Xapian::Error ) { IGNORE_RESULT (asprintf (, "A Xapian exception occurred opening database: %s\n", error.get_msg().c_str())); diff --git a/test/T730-user-header.sh b/test/T730-user-header.sh index ad32a5b4..1531f1d6 100755 --- a/test/T730-user-header.sh +++ b/test/T730-user-header.sh @@ -35,4 +35,25 @@ index.header.spam=X-Spam EOF test_expect_equal_file EXPECTED OUTPUT +test_begin_subtest "parse user prefix" +NOTMUCH_DEBUG_QUERY=t notmuch count 'list:"notmuch"' 2>&1 | grep Tmail >OUTPUT +cat < EXPECTED +Query((Tmail AND XUlist:notmuch@1)) +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "parse user prefix, stemmed" +NOTMUCH_DEBUG_QUERY=t notmuch count 'list:notmuch' 2>&1 | grep Tmail >OUTPUT +cat < EXPECTED +Query((Tmail AND ZXUlist:notmuch@1)) +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_begin_subtest "parse user prefix, phrase" +NOTMUCH_DEBUG_QUERY=t notmuch count 'list:notmuchmail.org' 2>&1 | grep Tmail >OUTPUT +cat < EXPECTED +Query((Tmail AND (XUlist:notmuchmail@1 PHRASE 2 XUlist:org@2))) +EOF +test_expect_equal_file EXPECTED OUTPUT + test_done -- 2.20.1 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 6/7] lib/database: index user headers.
There is a O(log(#user headers)) penalty for the second lookup of the prefix name. --- lib/database.cc | 6 ++ lib/index.cc | 28 lib/notmuch-private.h| 5 + test/T730-user-header.sh | 17 + 4 files changed, 56 insertions(+) diff --git a/lib/database.cc b/lib/database.cc index 19aff0e8..2219a76a 100644 --- a/lib/database.cc +++ b/lib/database.cc @@ -308,6 +308,12 @@ _setup_query_field_default (const prefix_t *prefix, notmuch_database_t *notmuch) notmuch->query_parser->add_boolean_prefix (prefix->name, prefix->prefix); } +notmuch_string_map_iterator_t * +_notmuch_database_user_headers (notmuch_database_t *notmuch) +{ +return _notmuch_string_map_iterator_create (notmuch->user_header, "", false); +} + const char * _user_prefix (void *ctx, const char* name) { diff --git a/lib/index.cc b/lib/index.cc index efd9da4c..ef3369fd 100644 --- a/lib/index.cc +++ b/lib/index.cc @@ -595,6 +595,32 @@ _index_encrypted_mime_part (notmuch_message_t *message, } +static notmuch_status_t +_notmuch_message_index_user_headers (notmuch_message_t *message, GMimeMessage *mime_message) +{ + +notmuch_database_t *notmuch = notmuch_message_get_database (message); +notmuch_string_map_iterator_t *iter = _notmuch_database_user_headers (notmuch); + +for (; _notmuch_string_map_iterator_valid (iter); +_notmuch_string_map_iterator_move_to_next (iter)) { + + const char *prefix_name = _notmuch_string_map_iterator_key (iter); + + const char *header_name = _notmuch_string_map_iterator_value (iter); + + const char *header = g_mime_object_get_header (GMIME_OBJECT (mime_message), header_name); + if (header) + _notmuch_message_gen_terms (message, prefix_name, header); +} + +if (iter) + _notmuch_string_map_iterator_destroy (iter); +return NOTMUCH_STATUS_SUCCESS; + +} + + notmuch_status_t _notmuch_message_index_file (notmuch_message_t *message, notmuch_indexopts_t *indexopts, @@ -625,6 +651,8 @@ _notmuch_message_index_file (notmuch_message_t *message, subject = g_mime_message_get_subject (mime_message); _notmuch_message_gen_terms (message, "subject", subject); +status = _notmuch_message_index_user_headers (message, mime_message); + _index_mime_part (message, indexopts, g_mime_message_get_mime_part (mime_message)); return NOTMUCH_STATUS_SUCCESS; diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index cf08411e..e46df9a8 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -652,6 +652,11 @@ _notmuch_string_map_iterator_value (notmuch_string_map_iterator_t *iterator); void _notmuch_string_map_iterator_destroy (notmuch_string_map_iterator_t *iterator); +/* Create an iterator for user headers. Destroy with + * _notmuch_string_map_iterator_destroy. Actually in database.cc*/ +notmuch_string_map_iterator_t * +_notmuch_database_user_headers (notmuch_database_t *notmuch); + /* tags.c */ notmuch_tags_t * diff --git a/test/T730-user-header.sh b/test/T730-user-header.sh index 1531f1d6..c08985b9 100755 --- a/test/T730-user-header.sh +++ b/test/T730-user-header.sh @@ -56,4 +56,21 @@ Query((Tmail AND (XUlist:notmuchmail@1 PHRASE 2 XUlist:org@2))) EOF test_expect_equal_file EXPECTED OUTPUT +test_begin_subtest "index user header" +notmuch config set index.header.list "List-Id" +notmuch reindex '*' +notmuch search --output=files list:notmuch | notmuch_search_files_sanitize | sort > OUTPUT +cat < EXPECTED +MAIL_DIR/bar/baz/05:2, +MAIL_DIR/bar/baz/23:2, +MAIL_DIR/bar/baz/24:2, +MAIL_DIR/bar/cur/20:2, +MAIL_DIR/bar/new/21:2, +MAIL_DIR/bar/new/22:2, +MAIL_DIR/foo/cur/08:2, +MAIL_DIR/foo/new/03:2, +MAIL_DIR/new/04:2, +EOF +test_expect_equal_file EXPECTED OUTPUT + test_done -- 2.20.1 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 4/7] lib: cache user prefixes in database object
This will be used to avoid needing a database access to resolve a db prefix from the corresponding UI prefix (e.g. when indexing). Arguably the setup of the seperate header map does not belong here, since it is about indexing rather than querying, but we currently don't have any other indexing setup to do. --- lib/database-private.h | 5 + lib/database.cc| 39 --- lib/notmuch-private.h | 9 + lib/thread.cc | 2 -- 4 files changed, 42 insertions(+), 13 deletions(-) diff --git a/lib/database-private.h b/lib/database-private.h index a499b259..57fddada 100644 --- a/lib/database-private.h +++ b/lib/database-private.h @@ -215,6 +215,11 @@ struct _notmuch_database { Xapian::ValueRangeProcessor *value_range_processor; Xapian::ValueRangeProcessor *date_range_processor; Xapian::ValueRangeProcessor *last_mod_range_processor; + +/* XXX it's slightly gross to use two parallel string->string maps + * here, but at least they are small */ +notmuch_string_map_t *user_prefix; +notmuch_string_map_t *user_header; }; /* Prior to database version 3, features were implied by the database diff --git a/lib/database.cc b/lib/database.cc index 4de79f79..6caa1311 100644 --- a/lib/database.cc +++ b/lib/database.cc @@ -299,8 +299,6 @@ prefix_t prefix_table[] = { NOTMUCH_FIELD_PROCESSOR}, }; -#define CONFIG_HEADER_PREFIX "index.header." - static void _setup_query_field_default (const prefix_t *prefix, notmuch_database_t *notmuch) { @@ -310,29 +308,48 @@ _setup_query_field_default (const prefix_t *prefix, notmuch_database_t *notmuch) notmuch->query_parser->add_boolean_prefix (prefix->name, prefix->prefix); } +const char * +_user_prefix (void *ctx, const char* name) +{ +return talloc_asprintf(ctx, "XU%s:", name); +} + static notmuch_status_t _setup_user_query_fields (notmuch_database_t *notmuch) { notmuch_config_list_t *list; notmuch_status_t status; +notmuch->user_prefix = _notmuch_string_map_create (notmuch); +if (notmuch->user_prefix == NULL) + return NOTMUCH_STATUS_OUT_OF_MEMORY; + +notmuch->user_header = _notmuch_string_map_create (notmuch); +if (notmuch->user_header == NULL) + return NOTMUCH_STATUS_OUT_OF_MEMORY; + status = notmuch_database_get_config_list (notmuch, CONFIG_HEADER_PREFIX, ); if (status) return status; + for (; notmuch_config_list_valid (list); notmuch_config_list_move_to_next (list)) { - prefix_t query_field { .name = NULL, .prefix = NULL, - .flags = NOTMUCH_FIELD_PROBABILISTIC | -NOTMUCH_FIELD_EXTERNAL - }; + prefix_t query_field; + + const char *key = notmuch_config_list_key (list) + + + sizeof (CONFIG_HEADER_PREFIX) - 1; - const char *key = notmuch_config_list_key (list) - + sizeof (CONFIG_HEADER_PREFIX) - 1; + _notmuch_string_map_append (notmuch->user_prefix, + key, + _user_prefix (notmuch, key)); - char *prefix = talloc_asprintf(notmuch, "XU%s:", key); + _notmuch_string_map_append (notmuch->user_header, + key, + notmuch_config_list_value (list)); - query_field.name = key; - query_field.prefix = prefix; + query_field.name = talloc_strdup(notmuch, key); + query_field.prefix = _user_prefix(notmuch, key); + query_field.flags = NOTMUCH_FIELD_PROBABILISTIC | NOTMUCH_FIELD_EXTERNAL; _setup_query_field_default (_field, notmuch); } diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index df32d39c..1ef26e37 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -181,6 +181,11 @@ typedef struct _notmuch_doc_id_set notmuch_doc_id_set_t; const char * _find_prefix (const char *name); +/* Lookup a prefix value by name, including possibly user defined prefixes + */ +const char * +_notmuch_database_prefix (notmuch_database_t *notmuch, const char *name); + char * _notmuch_message_id_compressed (void *ctx, const char *message_id); @@ -676,6 +681,10 @@ struct _notmuch_indexopts { _notmuch_crypto_t crypto; }; +#define CONFIG_HEADER_PREFIX "index.header." + +#define EMPTY_STRING(s) ((s)[0] == '\0') + NOTMUCH_END_DECLS #ifdef __cplusplus diff --git a/lib/thread.cc b/lib/thread.cc index 47c90664..ae830064 100644 --- a/lib/thread.cc +++ b/lib/thread.cc @@ -30,8 +30,6 @@ #define THREAD_DEBUG(format, ...) do {} while (0) /* ignored */ #endif -#define EMPTY_STRING(s) ((s)[0] == '\0') - struct _notmuch_thread { notmuch_database_t *notmuch; char *thread_id; -- 2.20.1 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 5/7] lib: support user prefix names in term generation
This should not change the indexing process yet as nothing calls _notmuch_message_gen_terms with a user prefix name. On the other hand, it should not break anything either. --- lib/database.cc | 20 lib/message.cc| 5 - lib/notmuch-private.h | 1 + 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/lib/database.cc b/lib/database.cc index 6caa1311..19aff0e8 100644 --- a/lib/database.cc +++ b/lib/database.cc @@ -405,6 +405,26 @@ _find_prefix (const char *name) return ""; } +/* Like find prefix, but include the possibility of user defined + * prefixes specific to this database */ + +const char * +_notmuch_database_prefix (notmuch_database_t *notmuch, const char *name) +{ +unsigned int i; + +/*XXX TODO: reduce code duplication */ +for (i = 0; i < ARRAY_SIZE (prefix_table); i++) { + if (strcmp (name, prefix_table[i].name) == 0) + return prefix_table[i].prefix; +} + +if (notmuch->user_prefix) + return _notmuch_string_map_get (notmuch->user_prefix, name); + +return NULL; +} + static const struct { /* NOTMUCH_FEATURE_* value. */ _notmuch_features value; diff --git a/lib/message.cc b/lib/message.cc index 6f2f6345..bbc5ef99 100644 --- a/lib/message.cc +++ b/lib/message.cc @@ -1434,7 +1434,10 @@ _notmuch_message_gen_terms (notmuch_message_t *message, term_gen->set_document (message->doc); if (prefix_name) { - const char *prefix = _find_prefix (prefix_name); + const char *prefix = _notmuch_database_prefix (message->notmuch, prefix_name); + + if (prefix == NULL) + return NOTMUCH_PRIVATE_STATUS_BAD_PREFIX; term_gen->set_termpos (message->termpos); term_gen->index_text (text, 1, prefix); diff --git a/lib/notmuch-private.h b/lib/notmuch-private.h index 1ef26e37..cf08411e 100644 --- a/lib/notmuch-private.h +++ b/lib/notmuch-private.h @@ -136,6 +136,7 @@ typedef enum _notmuch_private_status { /* Then add our own private values. */ NOTMUCH_PRIVATE_STATUS_TERM_TOO_LONG = NOTMUCH_STATUS_LAST_STATUS, NOTMUCH_PRIVATE_STATUS_NO_DOCUMENT_FOUND, +NOTMUCH_PRIVATE_STATUS_BAD_PREFIX, NOTMUCH_PRIVATE_STATUS_LAST_STATUS } notmuch_private_status_t; -- 2.20.1 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 2/7] cli/config: support user header index config
We don't do anything with this configuration information information yet, but nonetheless add a couple of regression tests to make sure we don't break standard functionality when we do use the configuration information. --- notmuch-config.c | 1 + test/T730-user-header.sh | 38 ++ 2 files changed, 39 insertions(+) create mode 100755 test/T730-user-header.sh diff --git a/notmuch-config.c b/notmuch-config.c index 1517d0ff..5112fecd 100644 --- a/notmuch-config.c +++ b/notmuch-config.c @@ -831,6 +831,7 @@ _stored_in_db (const char *item) { struct config_key db_configs[] = { {"index.decrypt", false}, + {"index.header.", true}, {"query.", true}, }; for (size_t i = 0; i < ARRAY_SIZE (db_configs); i++) { diff --git a/test/T730-user-header.sh b/test/T730-user-header.sh new file mode 100755 index ..ad32a5b4 --- /dev/null +++ b/test/T730-user-header.sh @@ -0,0 +1,38 @@ +#!/usr/bin/env bash +test_description='indexing user specified headers' +. $(dirname "$0")/test-lib.sh || exit 1 + +test_begin_subtest "error adding user header before initializing DB" +test_expect_code 1 "notmuch config set index.header.list \"List-Id\"" + +add_email_corpus + +notmuch search '*' | notmuch_search_sanitize > initial-threads +notmuch search --output=messages '*' > initial-message-ids +notmuch dump > initial-dump + +test_begin_subtest "adding user header" +test_expect_code 0 "notmuch config set index.header.list \"List-Id\"" + +test_begin_subtest "adding existing user header" +test_expect_code 0 "notmuch config set index.header.list \"List-Id\"" + +test_begin_subtest "retrieve user header" +output=$(notmuch config get index.header.list) +test_expect_equal "List-Id" "$output" + +test_begin_subtest 'reindex after adding header preserves threads' +notmuch reindex '*' +notmuch search '*' | notmuch_search_sanitize > OUTPUT +test_expect_equal_file initial-threads OUTPUT + +test_begin_subtest "List all user headers" +notmuch config set index.header.spam "X-Spam" +notmuch config list | grep ^index.header | notmuch_config_sanitize > OUTPUT +cat < EXPECTED +index.header.list=List-Id +index.header.spam=X-Spam +EOF +test_expect_equal_file EXPECTED OUTPUT + +test_done -- 2.20.1 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
[PATCH 7/7] doc: document user header indexing.
It's a bit odd that the primary documentation is in notmuch-config, but it is consistent with the "query:" prefix. --- doc/man1/notmuch-config.rst | 8 doc/man7/notmuch-search-terms.rst | 3 +++ 2 files changed, 11 insertions(+) diff --git a/doc/man1/notmuch-config.rst b/doc/man1/notmuch-config.rst index 89909808..b91cbfd3 100644 --- a/doc/man1/notmuch-config.rst +++ b/doc/man1/notmuch-config.rst @@ -195,6 +195,14 @@ The available configuration items are described below. Default: ``auto``. +**index.header.** **[STORED IN DATABASE]** +Define the query prefix , based on a mail header. For +example ``index.header.list=List-Id`` will add a probabilistic +prefix ``list:`` that searches the ``List-Id`` field. Adding a +prefix with same name as a predefined prefix is not supported. See +**notmuch-search-terms(7)** for a list of existing prefixes, and +an explanation of probabilistic prefixes. + **built_with.** Compile time feature . Current possibilities include "compact" (see **notmuch-compact(1)**) and "field_processor" (see diff --git a/doc/man7/notmuch-search-terms.rst b/doc/man7/notmuch-search-terms.rst index f7a39ceb..36ba804b 100644 --- a/doc/man7/notmuch-search-terms.rst +++ b/doc/man7/notmuch-search-terms.rst @@ -166,6 +166,9 @@ property:= can be present on a given message with several different values. See **notmuch-properties(7)** for more details. +User defined prefixes are also supported, see **notmuch-config(1)** for +details. + Operators - -- 2.20.1 ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
WIP2: index user headers
This obsoletes [1] This is getting closer to mergable, but it still needs at least to sanity check the names of user defined prefixes (see point (a) below). The main differences from [1] are (a) xapian prefixes are no longer defined via upper casing, as this is locale dependent. The do rely on a ":" separator, hence the need for some sanitization. (b) The caching of user header/prefix information is now done via string maps, and used more effectively during indexing. ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: Reply to content of "List-Post" header?
You can set message-subscribed-addresses or its cousins; then message-to-list-only will work for you. -- Brian Sniffen > On Mar 2, 2019, at 10:00 AM, Ralph Seichter wrote: > > * Gregor Zattler: > >> I do "R" for reply-to-all and then C-c C-l for message-to-list-only >> which reduces the To: and Cc: to the mailing list address. > > I tried both "C-c C-l" and "M-x message-to-list-only" on several > messages, but it does not seem to have any effect. I don't see any > error reports, but nothing happens. > >> I don't know how this works, though. I assume it evaluates List- >> headers. > > According to http://www.gnus.org/manual/big-message.html , Emacs Message > mode processes the "Mail-Followup-To" header, which seems to be a rarity > these days. "List-Post" et al apparently don't factor into it. > > -Ralph > ___ > notmuch mailing list > notmuch@notmuchmail.org > https://notmuchmail.org/mailman/listinfo/notmuch ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: Reply to content of "List-Post" header?
* Gregor Zattler: > I do "R" for reply-to-all and then C-c C-l for message-to-list-only > which reduces the To: and Cc: to the mailing list address. I tried both "C-c C-l" and "M-x message-to-list-only" on several messages, but it does not seem to have any effect. I don't see any error reports, but nothing happens. > I don't know how this works, though. I assume it evaluates List- > headers. According to http://www.gnus.org/manual/big-message.html , Emacs Message mode processes the "Mail-Followup-To" header, which seems to be a rarity these days. "List-Post" et al apparently don't factor into it. -Ralph ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch
Re: Reply to content of "List-Post" header?
Hi Ralph, * Ralph Seichter [2019-03-01; 23:26]: > Either my search-fu is lacking today, or there is really not much > information to be found about this: > > Using Notmuch with Emacs, the keys "r" and "R" are bound to "reply to > sender" and "reply to all", respectively. Neither is what I require when > it comes to mailing lists. Is there any way to "reply to list", i.e. to > only the address specified in the "List-Post" header? I do "R" for reply-to-all and then C-c C-l for message-to-list-only which reduces the To: and Cc: to the mailing list address. I don't know how this works, though. I assume it evaluates List- headers. Ciao; Gregor -- -... --- .-. . -.. ..--.. ...-.- ___ notmuch mailing list notmuch@notmuchmail.org https://notmuchmail.org/mailman/listinfo/notmuch