[LyX/master] FindAdv: Search for 'whole words' with help of modified regex.

Kornel Benko kornel at lyx.org
Sun Jan 10 22:02:29 UTC 2021


commit 29b9dd8b2f89f3741375ff5494aad03f22c7514f
Author: Kornel Benko <kornel at lyx.org>
Date:   Sun Jan 10 22:58:58 2021 +0100

    FindAdv: Search for 'whole words' with help of modified regex.
---
 src/lyxfind.cpp |   48 +++++++++++++++++++++++++++++++++++++++++++++---
 src/lyxfind.h   |    2 +-
 2 files changed, 46 insertions(+), 4 deletions(-)

diff --git a/src/lyxfind.cpp b/src/lyxfind.cpp
index a82fef2..5c72661 100644
--- a/src/lyxfind.cpp
+++ b/src/lyxfind.cpp
@@ -893,7 +893,7 @@ static MatchResult::range interpretMatch(MatchResult &oldres, MatchResult &newre
 
 class MatchStringAdv {
 public:
-	MatchStringAdv(lyx::Buffer & buf, FindAndReplaceOptions const & opt);
+	MatchStringAdv(lyx::Buffer & buf, FindAndReplaceOptions & opt);
 
 	/** Tests if text starting at the supplied position matches with the one provided to the MatchStringAdv
 	 ** constructor as opt.search, under the opt.* options settings.
@@ -2971,7 +2971,32 @@ void MatchStringAdv::CreateRegexp(FindAndReplaceOptions const & opt, string rege
 #endif
 }
 
-MatchStringAdv::MatchStringAdv(lyx::Buffer & buf, FindAndReplaceOptions const & opt)
+static void modifyRegexForMatchWord(string &t)
+{
+	string s("");
+	regex wordre("(\\\\)*((\\.|\\\\b))");
+	size_t lastpos = 0;
+	smatch sub;
+	for (sregex_iterator it(t.begin(), t.end(), wordre), end; it != end; ++it) {
+		sub = *it;
+		if ((sub.position(2) - sub.position(0)) % 2 == 1) {
+			continue;
+		}
+		else if (sub.str(2) == "\\\\b")
+			return;
+		if (lastpos < (size_t) sub.position(2))
+			s += t.substr(lastpos, sub.position(2) - lastpos);
+		s += "\\S";
+		lastpos = sub.position(2) + sub.length(2);
+	}
+	if (lastpos == 0)
+		return;
+	else if (lastpos < t.length())
+		s += t.substr(lastpos, t.length() - lastpos);
+      t = "\\b" + s + "\\b";
+}
+
+MatchStringAdv::MatchStringAdv(lyx::Buffer & buf, FindAndReplaceOptions & opt)
 	: p_buf(&buf), p_first_buf(&buf), opt(opt)
 {
 	static std::regex specialChars { R"([-[\]{}()*+?.,\^$|#\s\\])" };
@@ -3006,6 +3031,12 @@ MatchStringAdv::MatchStringAdv(lyx::Buffer & buf, FindAndReplaceOptions const &
 		string lead_as_regex_string = std::regex_replace(lead_as_string, specialChars,  R"(\$&)" );
 		par_as_string_nolead = par_as_string.substr(lead_size, par_as_string.size() - lead_size);
 		string par_as_regex_string_nolead = std::regex_replace(par_as_string_nolead, specialChars,  R"(\$&)" );
+		/* Handle whole words too in this case
+		*/
+		if (opt.matchword) {
+			par_as_regex_string_nolead = "\\b" + par_as_regex_string_nolead + "\\b";
+			opt.matchword = false;
+		}
 		string regexp_str = "(" + lead_as_regex_string + ")()" + par_as_regex_string_nolead;
 		string regexp2_str = "(" + lead_as_regex_string + ")(.*?)" + par_as_regex_string_nolead;
 		CreateRegexp(opt, regexp_str, regexp2_str);
@@ -3085,6 +3116,17 @@ MatchStringAdv::MatchStringAdv(lyx::Buffer & buf, FindAndReplaceOptions const &
 				string dest = "\\" + std::to_string(i+2);
 				while (regex_replace(par_as_string, par_as_string, orig, dest));
 			}
+			/* opt.matchword is ignored if using regex
+			  but expanding par_as_string with "\\b" is not appropriate here
+			  if regex contains for instance '.*' or '.+'
+			  1.) Nothing to do, if 'par_as_string' contains "\\b" already.
+			      (Means, that the user knows how to handle whole words
+			  2.) else replace '.' with "\\S" and prepend + append "\\b"
+			*/
+			if (opt.matchword) {
+				modifyRegexForMatchWord(par_as_string);
+				opt.matchword = false;
+			}
 			regexp_str = "(" + lead_as_regexp + ")()" + par_as_string;
 			regexp2_str = "(" + lead_as_regexp + ")(.*?)" + par_as_string;
 		}
@@ -4179,7 +4221,7 @@ static int findAdvReplace(BufferView * bv, FindAndReplaceOptions const & opt, Ma
 
 
 /// Perform a FindAdv operation.
-bool findAdv(BufferView * bv, FindAndReplaceOptions const & opt)
+bool findAdv(BufferView * bv, FindAndReplaceOptions & opt)
 {
 	DocIterator cur;
 	int pos_len = 0;
diff --git a/src/lyxfind.h b/src/lyxfind.h
index 9daf4c8..8b9a8f0 100644
--- a/src/lyxfind.h
+++ b/src/lyxfind.h
@@ -125,7 +125,7 @@ std::ostringstream & operator<<(std::ostringstream & os, lyx::FindAndReplaceOpti
 std::istringstream & operator>>(std::istringstream & is, lyx::FindAndReplaceOptions & opt);
 
 /// Perform a FindAdv operation.
-bool findAdv(BufferView * bv, FindAndReplaceOptions const & opt);
+bool findAdv(BufferView * bv, FindAndReplaceOptions & opt);
 
 /** Computes the simple-text or LaTeX export (depending on opt) of buf starting
  ** from cur and ending len positions after cur, if len is positive, or at the


More information about the lyx-cvs mailing list