[Patch v2] lib: regexp matching in 'subject' and 'from'

David Bremner david at tethera.net
Thu Jan 19 06:27:43 PST 2017


David Bremner <david at tethera.net> writes:

> the idea is that you can run
>
> % notmuch search re:subject:<your-favourite-regexp>
> % notmuch search re:from:<your-favourite-regexp>'
>
> or
>
> % notmuch search subject:"your usual phrase search"
> % notmuch search from:"usual phrase search"

I'm not sure how useful it is, but here's an interdiff.

diff --git a/lib/database-private.h b/lib/database-private.h
index e7cbed8f..92f4b72f 100644
--- a/lib/database-private.h
+++ b/lib/database-private.h
@@ -190,7 +190,8 @@ struct _notmuch_database {
 #if HAVE_XAPIAN_FIELD_PROCESSOR
     Xapian::FieldProcessor *date_field_processor;
     Xapian::FieldProcessor *query_field_processor;
-    Xapian::FieldProcessor *re_field_processor;
+    Xapian::FieldProcessor *re_from_field_processor;
+    Xapian::FieldProcessor *re_subject_field_processor;
 #endif
     Xapian::ValueRangeProcessor *last_mod_range_processor;
 };
diff --git a/lib/database.cc b/lib/database.cc
index 851a62d1..2b2f8f5e 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -1043,8 +1043,10 @@ notmuch_database_open_verbose (const char *path,
 	notmuch->query_parser->add_boolean_prefix("date", notmuch->date_field_processor);
 	notmuch->query_field_processor = new QueryFieldProcessor (*notmuch->query_parser, notmuch);
 	notmuch->query_parser->add_boolean_prefix("query", notmuch->query_field_processor);
-	notmuch->re_field_processor = new RegexpFieldProcessor (*notmuch->query_parser, notmuch);
-	notmuch->query_parser->add_boolean_prefix("re", notmuch->re_field_processor);
+	notmuch->re_from_field_processor = new RegexpFieldProcessor ("from", *notmuch->query_parser, notmuch);
+	notmuch->re_subject_field_processor = new RegexpFieldProcessor ("subject", *notmuch->query_parser, notmuch);
+	notmuch->query_parser->add_boolean_prefix("re_from", notmuch->re_from_field_processor);
+	notmuch->query_parser->add_boolean_prefix("re_subject", notmuch->re_subject_field_processor);
 #endif
 	notmuch->last_mod_range_processor = new Xapian::NumberValueRangeProcessor (NOTMUCH_VALUE_LAST_MOD, "lastmod:");
 
@@ -1141,8 +1143,10 @@ notmuch_database_close (notmuch_database_t *notmuch)
     notmuch->date_field_processor = NULL;
     delete notmuch->query_field_processor;
     notmuch->query_field_processor = NULL;
-    delete notmuch->re_field_processor;
-    notmuch->re_field_processor = NULL;
+    delete notmuch->re_from_field_processor;
+    notmuch->re_from_field_processor = NULL;
+    delete notmuch->re_subject_field_processor;
+    notmuch->re_subject_field_processor = NULL;
 #endif
 
     return status;
diff --git a/lib/regexp-fields.cc b/lib/regexp-fields.cc
index 4d3d9721..211ec02d 100644
--- a/lib/regexp-fields.cc
+++ b/lib/regexp-fields.cc
@@ -101,25 +101,10 @@ RegexpPostingSource::next (unused (double min_wt))
     }
 }
 
-static Xapian::valueno
-_find_slot (std::string prefix)
-{
-    if (prefix == "from")
-	return NOTMUCH_VALUE_FROM;
-    else if (prefix == "subject")
-	return NOTMUCH_VALUE_SUBJECT;
-    else
-	throw Xapian::QueryParserError ("unsupported regexp field '" + prefix + "'");
-}
-
 Xapian::Query
 RegexpFieldProcessor::operator() (const std::string & str)
 {
-    size_t pos = str.find_first_of (':');
-    std::string prefix = str.substr (0, pos);
-    std::string regexp = str.substr (pos + 1);
-
-    postings = new RegexpPostingSource (_find_slot (prefix), regexp);
+    postings = new RegexpPostingSource (slot, str);
     return Xapian::Query (postings);
 }
 #endif
diff --git a/lib/regexp-fields.h b/lib/regexp-fields.h
index 2c9c2d7e..c2c44167 100644
--- a/lib/regexp-fields.h
+++ b/lib/regexp-fields.h
@@ -61,13 +61,26 @@ class RegexpPostingSource : public Xapian::PostingSource
 
 class RegexpFieldProcessor : public Xapian::FieldProcessor {
  protected:
+    Xapian::valueno slot;
     Xapian::QueryParser &parser;
     notmuch_database_t *notmuch;
     RegexpPostingSource *postings = NULL;
 
+
+    static inline Xapian::valueno _find_slot (std::string prefix)
+    {
+	if (prefix == "from")
+	    return NOTMUCH_VALUE_FROM;
+	else if (prefix == "subject")
+	    return NOTMUCH_VALUE_SUBJECT;
+	else
+	    throw Xapian::QueryParserError ("unsupported regexp field '" + prefix + "'");
+    }
+
+
  public:
-    RegexpFieldProcessor (Xapian::QueryParser &parser_, notmuch_database_t *notmuch_)
-	: parser(parser_), notmuch(notmuch_) { };
+    RegexpFieldProcessor (std::string prefix, Xapian::QueryParser &parser_, notmuch_database_t *notmuch_)
+	: slot(_find_slot (prefix)), parser(parser_), notmuch(notmuch_) { };
 
     ~RegexpFieldProcessor () { delete postings; };
 
diff --git a/test/T630-regexp-query.sh b/test/T630-regexp-query.sh
index 3bbe47cf..1b25634d 100755
--- a/test/T630-regexp-query.sh
+++ b/test/T630-regexp-query.sh
@@ -10,15 +10,15 @@ if [ $NOTMUCH_HAVE_XAPIAN_FIELD_PROCESSOR -eq 1 ]; then
     notmuch search --output=messages from:cworth > cworth.msg-ids
 
     test_begin_subtest "regexp from search, case sensitive"
-    notmuch search --output=messages re:from:carl > OUTPUT
+    notmuch search --output=messages re_from:carl > OUTPUT
     test_expect_equal_file /dev/null OUTPUT
 
     test_begin_subtest "empty regexp or query"
-    notmuch search --output=messages re:from:carl or from:cworth > OUTPUT
+    notmuch search --output=messages re_from:carl or from:cworth > OUTPUT
     test_expect_equal_file cworth.msg-ids OUTPUT
 
     test_begin_subtest "non-empty regexp and query"
-    notmuch search  re:from:cworth and subject:patch > OUTPUT
+    notmuch search  re_from:cworth and subject:patch > OUTPUT
     cat <<EOF > EXPECTED
 thread:0000000000000008   2009-11-18 [1/2] Carl Worth| Alex Botero-Lowry; [notmuch] [PATCH] Error out if no query is supplied to search instead of going into an infinite loop (attachment inbox unread)
 thread:0000000000000007   2009-11-18 [1/2] Carl Worth| Ingmar Vanhassel; [notmuch] [PATCH] Typsos (inbox unread)
@@ -30,32 +30,32 @@ EOF
     test_expect_equal_file EXPECTED OUTPUT
 
     test_begin_subtest "regexp from search, duplicate term search"
-    notmuch search --output=messages re:from:cworth > OUTPUT
+    notmuch search --output=messages re_from:cworth > OUTPUT
     test_expect_equal_file cworth.msg-ids OUTPUT
 
     test_begin_subtest "long enough regexp matches only desired senders"
-    notmuch search --output=messages 're:"from:C.* Wo"' > OUTPUT
+    notmuch search --output=messages 're_from:"C.* Wo"' > OUTPUT
     test_expect_equal_file cworth.msg-ids OUTPUT
 
     test_begin_subtest "shorter regexp matches one more sender"
-    notmuch search --output=messages 're:"from:C.* W"' > OUTPUT
+    notmuch search --output=messages 're_from:"C.* W"' > OUTPUT
     (echo id:1258544095-16616-1-git-send-email-chris at chris-wilson.co.uk ; cat cworth.msg-ids) > EXPECTED
     test_expect_equal_file EXPECTED OUTPUT
 
     test_begin_subtest "regexp subject search, non-ASCII"
-    notmuch search --output=messages re:subject:accentué > OUTPUT
+    notmuch search --output=messages re_subject:accentué > OUTPUT
     echo id:877h1wv7mg.fsf at inf-8657.int-evry.fr > EXPECTED
     test_expect_equal_file EXPECTED OUTPUT
 
     test_begin_subtest "regexp subject search, punctuation"
-    notmuch search   re:subject:\'X\' > OUTPUT
+    notmuch search   re_subject:\'X\' > OUTPUT
     cat <<EOF > EXPECTED
 thread:0000000000000017   2009-11-18 [2/2] Keith Packard, Carl Worth; [notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox unread)
 EOF
     test_expect_equal_file EXPECTED OUTPUT
 
     test_begin_subtest "regexp subject search, no punctuation"
-    notmuch search  re:subject:X > OUTPUT
+    notmuch search  re_subject:X > OUTPUT
     cat <<EOF > EXPECTED
 thread:0000000000000017   2009-11-18 [2/2] Keith Packard, Carl Worth; [notmuch] [PATCH] Make notmuch-show 'X' (and 'x') commands remove inbox (and unread) tags (inbox unread)
 thread:000000000000000f   2009-11-18 [4/4] Jjgod Jiang, Alexander Botero-Lowry; [notmuch] Mac OS X/Darwin compatibility issues (inbox unread)
@@ -63,27 +63,18 @@ EOF
     test_expect_equal_file EXPECTED OUTPUT
 
     test_begin_subtest "combine regexp from and subject"
-    notmuch search  re:subject:-C and re:from:.an.k > OUTPUT
+    notmuch search  re_subject:-C and re_from:.an.k > OUTPUT
     cat <<EOF > EXPECTED
 thread:0000000000000018   2009-11-17 [1/2] Jan Janak| Carl Worth; [notmuch] [PATCH] Older versions of install do not support -C. (inbox unread)
 EOF
     test_expect_equal_file EXPECTED OUTPUT
 
-    test_begin_subtest "bad subprefix"
-    notmuch search 're:unsupported:.*' 1>OUTPUT 2>&1
-    cat <<EOF > EXPECTED
-notmuch search: A Xapian exception occurred
-A Xapian exception occurred performing query: unsupported regexp field 'unsupported'
-Query string was: re:unsupported:.*
-EOF
-    test_expect_equal_file EXPECTED OUTPUT
-
     test_begin_subtest "regexp error reporting"
-    notmuch search 're:from:unbalanced[' 1>OUTPUT 2>&1
+    notmuch search 're_from:unbalanced[' 1>OUTPUT 2>&1
     cat <<EOF > EXPECTED
 notmuch search: A Xapian exception occurred
 A Xapian exception occurred performing query: Invalid regular expression
-Query string was: re:from:unbalanced[
+Query string was: re_from:unbalanced[
 EOF
     test_expect_equal_file EXPECTED OUTPUT
 fi


More information about the notmuch mailing list