From: Tommaso Cucinotta Date: Thu, 25 Aug 2011 19:16:14 +0000 (+0000) Subject: Fixed longstanding bug in Advanced Find&Replace, when dealing with documents containi... X-Git-Tag: 2.1.0beta1~2794 X-Git-Url: https://git.lyx.org/gitweb/?a=commitdiff_plain;h=ef7a142f3f4e5937dabf7fb8fc7957bf351e166d;p=features.git Fixed longstanding bug in Advanced Find&Replace, when dealing with documents containing braces. Corresponding test-case needed a fix as well and now it is passed. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@39518 a592a061-630c-0410-9148-cb99ea01b6c8 --- diff --git a/development/autotests/findadv-re-03-in.txt b/development/autotests/findadv-re-03-in.txt index c86ac718d9..4456458866 100644 --- a/development/autotests/findadv-re-03-in.txt +++ b/development/autotests/findadv-re-03-in.txt @@ -24,7 +24,7 @@ TestBegin test.lyx -dbg find > lyx-log.txt 2>&1 KK: \CF KK: \Axregexp-mode\[Return]\\}\[Return] TestEnd -Assert pcregrep -M 'Putting selection at .*idx: 0 par: 0 pos: 5\n with len: 1' lyx-log.txt +Assert pcregrep -M 'Putting selection at .*idx: 0 par: 0 pos: 6\n with len: 1' lyx-log.txt # TestBegin test.lyx -dbg find > lyx-log.txt 2>&1 KK: \CF @@ -32,4 +32,4 @@ KK: \CF KK: \Az\Ag\Ae KK: \Axregexp-mode\[Return]\\}\[Return] TestEnd -Assert pcregrep -M 'Putting selection at .*idx: 0 par: 0 pos: 5\n with len: 1' lyx-log.txt +Assert pcregrep -M 'Putting selection at .*idx: 0 par: 0 pos: 6\n with len: 1' lyx-log.txt diff --git a/src/lyxfind.cpp b/src/lyxfind.cpp index 16527c0290..af27be2b91 100644 --- a/src/lyxfind.cpp +++ b/src/lyxfind.cpp @@ -507,7 +507,7 @@ Escapes const & get_regexp_escapes() escape_map.push_back(pair(".", "\\.")); escape_map.push_back(pair("\\", "(?:\\\\|\\\\backslash)")); escape_map.push_back(pair("~", "(?:\\\\textasciitilde|\\\\sim)")); - escape_map.push_back(pair("^", "(?:\\^|\\\\textasciicircum\\{\\}|\\\\mathcircumflex")); + escape_map.push_back(pair("^", "(?:\\^|\\\\textasciicircum\\{\\}|\\\\mathcircumflex)")); } return escape_map; } @@ -517,12 +517,12 @@ Escapes const & get_lyx_unescapes() { static Escapes escape_map; if (escape_map.empty()) { escape_map.push_back(pair("\\%", "%")); - escape_map.push_back(pair("\\{", "{")); - escape_map.push_back(pair("\\}", "}")); escape_map.push_back(pair("\\mathcircumflex ", "^")); escape_map.push_back(pair("\\mathcircumflex", "^")); escape_map.push_back(pair("\\backslash ", "\\")); escape_map.push_back(pair("\\backslash", "\\")); + escape_map.push_back(pair("\\\\{", "_x_<")); + escape_map.push_back(pair("\\\\}", "_x_>")); escape_map.push_back(pair("\\sim ", "~")); escape_map.push_back(pair("\\sim", "~")); } @@ -593,7 +593,7 @@ string escape_for_regex(string s, bool match_latex) { size_t pos = 0; while (pos < s.size()) { - size_t new_pos = s.find("\\regexp{{{", pos); + size_t new_pos = s.find("\\regexp{", pos); if (new_pos == string::npos) new_pos = s.size(); LYXERR(Debug::FIND, "new_pos: " << new_pos); @@ -607,20 +607,24 @@ string escape_for_regex(string s, bool match_latex) LYXERR(Debug::FIND, "new_pos: " << new_pos); if (new_pos == s.size()) break; - size_t end_pos = s.find("}}}", new_pos + 10); // find_matching_brace(s, new_pos + 7); + size_t end_pos = s.find("\\endregexp{}}", new_pos + 8); // find_matching_brace(s, new_pos + 7); LYXERR(Debug::FIND, "end_pos: " << end_pos); - t = apply_escapes(s.substr(new_pos + 10, end_pos - (new_pos + 10)), get_lyx_unescapes()); - if (match_latex) + t = s.substr(new_pos + 8, end_pos - (new_pos + 8)); + LYXERR(Debug::FIND, "t in regexp : " << t); + t = apply_escapes(t, get_lyx_unescapes()); + LYXERR(Debug::FIND, "t in regexp [lyx]: " << t); + if (match_latex) { t = apply_escapes(t, get_regexp_latex_escapes()); - LYXERR(Debug::FIND, "t : " << t); + LYXERR(Debug::FIND, "t in regexp [ltx]: " << t); + } if (end_pos == s.size()) { s.replace(new_pos, end_pos - new_pos, t); pos = s.size(); LYXERR(Debug::FIND, "Regexp after \\regexp{} removal: " << s); break; } - s.replace(new_pos, end_pos + 3 - new_pos, t); - LYXERR(Debug::FIND, "Regexp after \\regexp{} removal: " << s); + s.replace(new_pos, end_pos + 13 - new_pos, t); + LYXERR(Debug::FIND, "Regexp after \\regexp{...\\endregexp{}} removal: " << s); pos = new_pos + t.size(); LYXERR(Debug::FIND, "pos: " << pos); } @@ -725,7 +729,7 @@ private: ** @todo Normalization should also expand macros, if the corresponding ** search option was checked. **/ - string normalize(docstring const & s) const; + string normalize(docstring const & s, bool hack_braces) const; // normalized string to search string par_as_string; // regular expression to use for searching @@ -829,12 +833,13 @@ MatchStringAdv::MatchStringAdv(lyx::Buffer & buf, FindAndReplaceOptions const & : p_buf(&buf), p_first_buf(&buf), opt(opt) { Buffer & find_buf = *theBufferList().getBuffer(FileName(to_utf8(opt.find_buf_name)), true); - par_as_string = normalize(stringifySearchBuffer(find_buf, opt)); + docstring const & ds = stringifySearchBuffer(find_buf, opt); + use_regexp = lyx::to_utf8(ds).find("\\regexp{") != std::string::npos; + // When using regexp, braces are hacked already by escape_for_regex() + par_as_string = normalize(ds, !use_regexp); open_braces = 0; close_wildcards = 0; - use_regexp = par_as_string.find("\\regexp") != std::string::npos; - size_t lead_size = 0; if (!opt.ignoreformat) { lead_size = identifyLeading(par_as_string); @@ -893,7 +898,7 @@ int MatchStringAdv::findAux(DocIterator const & cur, int len, bool at_begin) con { docstring docstr = stringifyFromForSearch(opt, cur, len); LYXERR(Debug::FIND, "Matching against '" << lyx::to_utf8(docstr) << "'"); - string str = normalize(docstr); + string str = normalize(docstr, true); LYXERR(Debug::FIND, "After normalization: '" << str << "'"); if (! use_regexp) { LYXERR(Debug::FIND, "Searching in normal mode: par_as_string='" << par_as_string << "', str='" << str << "'"); @@ -959,7 +964,7 @@ int MatchStringAdv::operator()(DocIterator const & cur, int len, bool at_begin) } -string MatchStringAdv::normalize(docstring const & s) const +string MatchStringAdv::normalize(docstring const & s, bool hack_braces) const { string t; if (! opt.casesensitive) @@ -980,6 +985,19 @@ string MatchStringAdv::normalize(docstring const & s) const LYXERR(Debug::FIND, "Removing stale empty \\emph{}, \\textbf{}, \\*section{} macros from: " << t); while (regex_replace(t, t, "\\\\(emph|textbf|subsubsection|subsection|section|subparagraph|paragraph|part)(\\{\\})+", "")) LYXERR(Debug::FIND, " further removing stale empty \\emph{}, \\textbf{} macros from: " << t); + + // FIXME - check what preceeds the brace + if (hack_braces) { + if (opt.ignoreformat) + while (regex_replace(t, t, "\\{", "_x_<") + || regex_replace(t, t, "\\}", "_x_>")) + LYXERR(Debug::FIND, "After {} replacement: '" << t << "'"); + else + while (regex_replace(t, t, "\\\\\\{", "_x_<") + || regex_replace(t, t, "\\\\\\}", "_x_>")) + LYXERR(Debug::FIND, "After {} replacement: '" << t << "'"); + } + return t; } diff --git a/src/mathed/InsetMathHull.cpp b/src/mathed/InsetMathHull.cpp index d92c33c75a..50fb014dc4 100644 --- a/src/mathed/InsetMathHull.cpp +++ b/src/mathed/InsetMathHull.cpp @@ -743,6 +743,8 @@ void InsetMathHull::validate(LaTeXFeatures & features) const string("\\newcommand{\\regexp}[1]{\\fcolorbox{") + frcol + string("}{") + bgcol + string("}{\\ensuremath{\\mathtt{#1}}}}")); + features.addPreambleSnippet( + string("\\newcommand{\\endregexp}{}")); } // Validation is necessary only if not using AMS math. @@ -807,7 +809,7 @@ void InsetMathHull::header_write(WriteStream & os) const break; case hullRegexp: - os << "\\regexp{{{"; + os << "\\regexp{"; break; default: @@ -852,7 +854,8 @@ void InsetMathHull::footer_write(WriteStream & os) const break; case hullRegexp: - os << "}}}"; + // Only used as a heuristic to find the regexp termination, when searching in ignore-format mode + os << "\\endregexp{}}"; break; default: