[WIP patch] lib: Add regexp expansion for for tags and paths

David Bremner david at tethera.net
Tue Mar 7 18:40:35 PST 2017


>From a ui perspective this looks similar to what was already provided
for from, subject, and mid, but the implimentation is quite
different. It uses the database's list of terms to construct a term
based query equivalent to the passed regular expression.
---

this applies on top of olly's update to RegexpPostingSource and the
mid regexp patch. No docs or tests so far.  try e.g. folder:/notmuch/
or tag:/notmuch/. In principle we shouldn't need to store all the
terms before passing them to the Query constructor.

 lib/database.cc      | 12 ++++++++----
 lib/regexp-fields.cc | 24 +++++++++++++++++++-----
 2 files changed, 27 insertions(+), 9 deletions(-)

diff --git a/lib/database.cc b/lib/database.cc
index 09337602..a2c7d6f6 100644
--- a/lib/database.cc
+++ b/lib/database.cc
@@ -259,12 +259,15 @@ prefix_t prefix_table[] = {
     { "file-direntry",		"XFDIRENTRY",	NOTMUCH_FIELD_NO_FLAGS },
     { "directory-direntry",	"XDDIRENTRY",	NOTMUCH_FIELD_NO_FLAGS },
     { "thread",			"G",		NOTMUCH_FIELD_EXTERNAL },
-    { "tag",			"K",		NOTMUCH_FIELD_EXTERNAL },
-    { "is",			"K",		NOTMUCH_FIELD_EXTERNAL },
+    { "tag",			"K",		NOTMUCH_FIELD_EXTERNAL |
+						NOTMUCH_FIELD_PROCESSOR },
+    { "is",			"K",		NOTMUCH_FIELD_EXTERNAL |
+					        NOTMUCH_FIELD_PROCESSOR },
     { "id",			"Q",		NOTMUCH_FIELD_EXTERNAL },
     { "mid",			"Q",		NOTMUCH_FIELD_EXTERNAL |
 						NOTMUCH_FIELD_PROCESSOR },
-    { "path",			"P",		NOTMUCH_FIELD_EXTERNAL },
+    { "path",			"P",		NOTMUCH_FIELD_EXTERNAL|
+						NOTMUCH_FIELD_PROCESSOR },
     { "property",		"XPROPERTY",	NOTMUCH_FIELD_EXTERNAL },
     /*
      * Unconditionally add ':' to reduce potential ambiguity with
@@ -272,7 +275,8 @@ prefix_t prefix_table[] = {
      * letters. See Xapian document termprefixes.html for related
      * discussion.
      */
-    { "folder",			"XFOLDER:",	NOTMUCH_FIELD_EXTERNAL },
+    { "folder",			"XFOLDER:",	NOTMUCH_FIELD_EXTERNAL |
+						NOTMUCH_FIELD_PROCESSOR },
 #if HAVE_XAPIAN_FIELD_PROCESSOR
     { "date",			NULL,		NOTMUCH_FIELD_EXTERNAL |
 						NOTMUCH_FIELD_PROCESSOR },
diff --git a/lib/regexp-fields.cc b/lib/regexp-fields.cc
index fad9e7a5..ab3766f4 100644
--- a/lib/regexp-fields.cc
+++ b/lib/regexp-fields.cc
@@ -138,7 +138,7 @@ static inline Xapian::valueno _find_slot (std::string prefix)
     else if (prefix == "mid")
 	return NOTMUCH_VALUE_MESSAGE_ID;
     else
-	throw Xapian::QueryParserError ("unsupported regexp field '" + prefix + "'");
+	return Xapian::BAD_VALUENO;
 }
 
 RegexpFieldProcessor::RegexpFieldProcessor (std::string prefix,
@@ -156,10 +156,24 @@ RegexpFieldProcessor::RegexpFieldProcessor (std::string prefix,
 Xapian::Query
 RegexpFieldProcessor::operator() (const std::string & str)
 {
-    if (str.at (0) == '/') {
-	if (str.at (str.size () - 1) == '/'){
-	    RegexpPostingSource *postings = new RegexpPostingSource (slot, str.substr(1,str.size () - 2));
-	    return Xapian::Query (postings->release ());
+    if (str.length() > 0 && str.at (0) == '/') {
+	if (str.length() > 1 && str.at (str.size () - 1) == '/'){
+	    std::string regexp_str = str.substr(1,str.size () - 2);
+	    if (slot != Xapian::BAD_VALUENO) {
+		RegexpPostingSource *postings = new RegexpPostingSource (slot, regexp_str);
+		return Xapian::Query (postings->release ());
+	    } else {
+		std::vector<std::string> terms;
+		regex_t regexp;
+
+		compile_regex(regexp, regexp_str.c_str ());
+		for (Xapian::TermIterator it = notmuch->xapian_db->allterms_begin (term_prefix);
+		     it != notmuch->xapian_db->allterms_end (); ++it) {
+		    if (regexec (&regexp, (*it).c_str (), 0, NULL, 0) == 0)
+			terms.push_back(*it);
+		}
+		return Xapian::Query (Xapian::Query::OP_OR, terms.begin(), terms.end());
+	    }
 	} else {
 	    throw Xapian::QueryParserError ("unmatched regex delimiter in '" + str + "'");
 	}
-- 
2.11.0



More information about the notmuch mailing list