]> git.lyx.org Git - features.git/commitdiff
FindAdv: Search for 'whole words' with help of modified regex.
authorKornel Benko <kornel@lyx.org>
Sun, 10 Jan 2021 21:58:58 +0000 (22:58 +0100)
committerKornel Benko <kornel@lyx.org>
Sun, 10 Jan 2021 22:02:55 +0000 (23:02 +0100)
src/lyxfind.cpp
src/lyxfind.h

index a82fef2e3f2e644590a9e00d6787b20a9c1a0f77..5c72661b19dd26a3de2785e7c15c66163f4c7116 100644 (file)
@@ -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;
index 9daf4c8d74e560433d1ba11c01c3a04175562afe..8b9a8f09f06913de706f5c9f458a47ef8642b169 100644 (file)
@@ -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