// @TODO Support \item[text]
// Kornel: Added textsl, textsf, textit, texttt and noun
// + allow to search for colored text too
- while (regex_replace(t, t, REGEX_BOS "\\\\(((emph|noun|minisec|text(bf|md|sl|sf|it|tt))|((textcolor|foreignlanguage)\\{[a-z]+\\})|(u|uu)line|(s|x)out|uwave)|((sub)?(((sub)?section)|paragraph)|part|chapter)\\*?)\\{", "")
+ while (regex_replace(t, t, REGEX_BOS "\\\\(((footnotesize|tiny|scriptsize|small|large|Large|LARGE|huge|Huge|emph|noun|minisec|text(bf|md|sl|sf|it|tt))|((textcolor|foreignlanguage)\\{[a-z]+\\})|(u|uu)line|(s|x)out|uwave)|((sub)?(((sub)?section)|paragraph)|part|chapter)\\*?)\\{", "")
|| regex_replace(t, t, REGEX_BOS "\\$", "")
|| regex_replace(t, t, REGEX_BOS "\\\\\\[ ", "")
|| regex_replace(t, t, REGEX_BOS " ?\\\\item\\{[a-z]+\\}", "")
static Features identifyFeatures(string const & s)
{
static regex const feature("\\\\(([a-z]+(\\{([a-z]+)\\}|\\*)?))\\{");
- static regex const valid("^(((emph|noun|text(bf|md|sl|sf|it|tt)|(textcolor|foreignlanguage|item)\\{[a-z]+\\})|(u|uu)line|(s|x)out|uwave)|((sub)?(((sub)?section)|paragraph)|part|chapter)\\*?)$");
+ static regex const valid("^(((footnotesize|tiny|scriptsize|small|large|Large|LARGE|huge|Huge|emph|noun|text(bf|md|sl|sf|it|tt)|(textcolor|foreignlanguage|item)\\{[a-z]+\\})|(u|uu)line|(s|x)out|uwave)|((sub)?(((sub)?section)|paragraph)|part|chapter)\\*?)$");
smatch sub;
bool displ = true;
Features info;
class KeyInfo {
public:
enum KeyType {
+ /* Char type with content discarded
+ * like \hspace{1cm} */
+ noContent,
+ /* Char, like \backslash */
isChar,
+ /* \part, \section*, ... */
isSectioning,
- isMain, /* for \\foreignlanguage */
+ /* \foreignlanguage{ngerman}, ... */
+ isMain,
+ /* inside \code{} or \footnote{}
+ * to discard language in content */
+ noMain,
isRegex,
+ /* \begin{eqnarray}...\end{eqnarray}, ... $...$ */
isMath,
+ /* fonts, colors, markups, ... */
isStandard,
+ /* footnotesize, ... large, ...
+ * Ignore all of them */
isSize,
invalid,
+ /* inputencoding, shortcut, ...
+ * Discard also content, because they do not help in search */
doRemove,
+ /* item */
isList,
- isIgnored /* to be ignored by creating infos */
+ /* tex, latex, ... like isChar */
+ isIgnored
};
KeyInfo()
: keytype(invalid),
head(""),
+ _tokensize(-1),
+ _tokenstart(-1),
+ _dataStart(-1),
+ _dataEnd(-1),
parenthesiscount(1),
disabled(false),
used(false)
{};
KeyInfo(KeyType type, int parcount, bool disable)
: keytype(type),
+ _tokensize(-1),
+ _tokenstart(-1),
+ _dataStart(-1),
+ _dataEnd(-1),
parenthesiscount(parcount),
disabled(disable),
used(false) {};
class Intervall {
bool isPatternString;
public:
- Intervall(bool isPattern) : isPatternString(isPattern), ignoreidx(-1), actualdeptindex(0) { depts[0] = 0;};
+ explicit Intervall(bool isPattern) :
+ isPatternString(isPattern),
+ ignoreidx(-1),
+ actualdeptindex(0) { depts[0] = 0; closes[0] = 0;};
string par;
int ignoreidx;
int depts[MAXOPENED];
void removeHead(KeyInfo&, int count=0);
public:
- LatexInfo(string par, bool isPatternString) : interval(isPatternString) {
+ LatexInfo(string par, bool isPatternString) : entidx(-1), interval(isPatternString) {
interval.par = par;
buildKeys(isPatternString);
entries = vector<KeyInfo>();
m.mathSize = end - start;
entries.push_back(m);
}
- bool evaluating(size_t pos) {
- while (actualIdx < entries.size()) {
- if (pos < entries[actualIdx].mathStart)
- return false;
- if (pos < entries[actualIdx].mathEnd)
- return true;
- actualIdx++;
- }
- return false;
- }
bool empty() { return entries.empty(); };
size_t getEndPos() {
if (entries.empty() || (actualIdx >= entries.size())) {
bool evaluatingRegexp = false;
MathInfo mi;
bool evaluatingMath = false;
+ bool evaluatingCode = false;
+ size_t codeEnd = 0;
+ int codeStart = -1;
KeyInfo found;
bool math_end_waiting = false;
size_t math_pos = 10000;
if (key == "") {
if (sub.str(0)[0] == '\\')
key = sub.str(0)[1];
- else
+ else {
key = sub.str(0);
+ if (key == "$") {
+ size_t k_pos = sub.position(size_t(0));
+ if ((k_pos > 0) && (interval.par[k_pos - 1] == '\\')) {
+ // Escaped '$', ignoring
+ continue;
+ }
+ }
+ }
};
if (evaluatingRegexp) {
if (sub.str(1).compare("endregexp") == 0) {
found._tokenstart = sub.position(size_t(0));
if (found.parenthesiscount == 0) {
// Probably to be discarded
- char following = interval.par[sub.position(size_t(0)) + sub.str(3).length() + 1];
+ size_t following_pos = sub.position(size_t(0)) + sub.str(3).length() + 1;
+ char following = interval.par[following_pos];
if (following == ' ')
found.head = "\\" + sub.str(3) + " ";
else if (following == '=') {
found._tokensize = found.head.length();
found._dataStart = found._tokenstart + found.head.length();
size_t endpos = interval.findclosing(found._dataStart, interval.par.length());
+ if (found.keytype == KeyInfo::noMain) {
+ evaluatingCode = true;
+ codeEnd = endpos;
+ codeStart = found._dataStart;
+ }
+ else if (evaluatingCode) {
+ if (size_t(found._dataStart) > codeEnd)
+ evaluatingCode = false;
+ else if (found.keytype == KeyInfo::isMain) {
+ // Disable this key, treate it as standard
+ found.keytype = KeyInfo::isStandard;
+ found.disabled = true;
+ if ((codeEnd == interval.par.length()) &&
+ (found._tokenstart == codeStart)) {
+ // trickery, because the code inset starts
+ // with \selectlanguage ...
+ codeEnd = endpos;
+ if (entries.size() > 1) {
+ entries[entries.size()-1]._dataEnd = codeEnd;
+ }
+ }
+ }
+ }
if ((endpos == interval.par.length()) &&
(found.keytype == KeyInfo::doRemove)) {
// Missing closing => error in latex-input?
}
else
found._dataEnd = endpos;
- if (isPatternString) {
- keys[key].used = true;
- }
+ }
+ if (isPatternString) {
+ keys[key].used = true;
}
}
entries.push_back(found);
static bool keysBuilt = false;
if (keysBuilt && !isPatternString) return;
- // Know standard keys with 1 parameter.
+ // Known standard keys with 1 parameter.
// Split is done, if not at start of region
makeKey("textsf|textss|texttt", KeyInfo(KeyInfo::isStandard, 1, ignoreFormats.getFamily()), isPatternString);
makeKey("textbf", KeyInfo(KeyInfo::isStandard, 1, ignoreFormats.getSeries()), isPatternString);
// Know charaters
// No split
- makeKey("backslash|textbackslash|textasciicircum|textasciitilde|ldots", KeyInfo(KeyInfo::isChar, 1, false), isPatternString);
+ makeKey("backslash|textbackslash|slash", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+ makeKey("textasciicircum|textasciitilde", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+ makeKey("textasciiacute", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+ makeKey("dots|ldots", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+ // Spaces
+ makeKey("quad|qquad|hfill|dotfill", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+ makeKey("textvisiblespace|nobreakspace", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+ makeKey("negthickspace|negmedspace|negthinspace", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+ // Skip
+ makeKey("enskip|smallskip|medskip|bigskip|vfill", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+ // Custom space/skip, remove the content (== length value)
+ makeKey("vspace|hspace|mspace", KeyInfo(KeyInfo::noContent, 1, false), isPatternString);
// Found in fr/UserGuide.lyx
- makeKey("og|fg|textvisiblespace|lyx", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
- makeKey("textquotedbl|lyxarrow", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
-
+ makeKey("og|fg", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+ // quotes
+ makeKey("textquotedbl|quotesinglbase|lyxarrow", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
+ makeKey("textquotedblleft|textquotedblright", KeyInfo(KeyInfo::isChar, 0, false), isPatternString);
// Known macros to remove (including their parameter)
// No split
- makeKey("inputencoding|shortcut|label|ref", KeyInfo(KeyInfo::doRemove, 1, false), isPatternString);
+ makeKey("inputencoding|shortcut|label|ref|index", KeyInfo(KeyInfo::doRemove, 1, false), isPatternString);
+
+ // handle like standard keys with 1 parameter.
+ makeKey("url|href|vref|thanks", KeyInfo(KeyInfo::isStandard, 1, false), isPatternString);
// Macros to remove, but let the parameter survive
// No split
- makeKey("url|href|menuitem|footnote|code|index|textmd|textrm", KeyInfo(KeyInfo::isStandard, 1, true), isPatternString);
+ makeKey("menuitem|textmd|textrm", KeyInfo(KeyInfo::isStandard, 1, true), isPatternString);
+
+ // Remove language spec from content of these insets
+ makeKey("code|footnote", KeyInfo(KeyInfo::noMain, 1, false), isPatternString);
// Same effect as previous, parameter will survive (because there is no one anyway)
// No split
- makeKey("noindent", KeyInfo(KeyInfo::isStandard, 0, true), isPatternString);
+ makeKey("noindent|textcompwordmark", KeyInfo(KeyInfo::isStandard, 0, true), isPatternString);
// Remove table decorations
makeKey("hline|tabularnewline|toprule|bottomrule|midrule", KeyInfo(KeyInfo::doRemove, 0, true), isPatternString);
// Discard shape-header
makeKey("triangleuppar|triangledownpar|droppar", KeyInfo(KeyInfo::isStandard, 1, true), isPatternString);
makeKey("triangleleftpar|shapepar|dropuppar", KeyInfo(KeyInfo::isStandard, 1, true), isPatternString);
// like ('tiny{}' or '\tiny ' ... )
- makeKey("footnotesize|tiny|scriptsize|small|large|Large|LARGE|huge|Huge", KeyInfo(KeyInfo::isSize, 0, true), isPatternString);
+ makeKey("footnotesize|tiny|scriptsize|small|large|Large|LARGE|huge|Huge", KeyInfo(KeyInfo::isSize, 0, false), isPatternString);
// Survives, like known character
- makeKey("lyx|latex|tex", KeyInfo(KeyInfo::isIgnored, 0, false), isPatternString);
+ makeKey("lyx|latex|latexe|tex", KeyInfo(KeyInfo::isIgnored, 0, false), isPatternString);
makeKey("item", KeyInfo(KeyInfo::isList, 1, false), isPatternString);
makeKey("begin|end", KeyInfo(KeyInfo::isMath, 1, false), isPatternString);
makeKey("[|]", KeyInfo(KeyInfo::isMath, 1, false), isPatternString);
makeKey("$", KeyInfo(KeyInfo::isMath, 1, false), isPatternString);
- makeKey("par|uldepth|ULdepth|protect", KeyInfo(KeyInfo::doRemove, 0, true), isPatternString);
+ makeKey("par|uldepth|ULdepth|protect|nobreakdash", KeyInfo(KeyInfo::isStandard, 0, true), isPatternString);
// Remove RTL/LTR marker
- makeKey("l|r|textlr|textfr|textar|beginl|endl", KeyInfo(KeyInfo::doRemove, 0, true), isPatternString);
+ makeKey("l|r|textlr|textfr|textar|beginl|endl", KeyInfo(KeyInfo::isStandard, 0, true), isPatternString);
if (isPatternString) {
// Allow the first searched string to rebuild the keys too
int i = 0;
for (idx = 0; idx <= ignoreidx; idx++) {
if (i < lastpos) {
- int printsize;
if (i <= borders[idx].low) {
+ int printsize;
if (borders[idx].low > lastpos)
printsize = lastpos - i;
else
int nextKeyIdx = 0;
switch (actual.keytype)
{
+ case KeyInfo::noContent: { /* char like "\hspace{2cm}" */
+ interval.addIntervall(actual._dataStart, actual._dataEnd);
+ }
+ // fall through
case KeyInfo::isChar: {
nextKeyIdx = getNextKey();
break;
}
case KeyInfo::isSize: {
- if (actual.disabled) {
- // Allways disabled
+ if (actual.disabled || (interval.par[actual._dataStart] != '{') || (interval.par[actual._dataStart-1] == ' ')) {
processRegion(actual._dataEnd, actual._dataEnd+1); /* remove possibly following {} */
interval.addIntervall(actual._tokenstart, actual._dataEnd+1);
nextKeyIdx = getNextKey();
} else {
+ // Here _dataStart points to '{', so correct it
+ actual._dataStart += 1;
+ actual._tokensize += 1;
+ actual.parenthesiscount = 1;
+ if (interval.par[actual._dataStart] == '}') {
+ // Determine the end if used like '{\tiny{}...}'
+ actual._dataEnd = interval.findclosing(actual._dataStart+1, interval.par.length()) + 1;
+ interval.addIntervall(actual._dataStart, actual._dataStart+1);
+ }
+ else {
+ // Determine the end if used like '\tiny{...}'
+ actual._dataEnd = interval.findclosing(actual._dataStart, interval.par.length()) + 1;
+ }
// Split on this key if not at start
int start = interval.nextNotIgnored(previousStart);
if (start < actual._tokenstart) {
}
break;
}
+ case KeyInfo::noMain:
+ // fall through
case KeyInfo::isStandard: {
if (actual.disabled) {
removeHead(actual);
if ((actual.keytype == KeyInfo::isMain) && actual.disabled) {
interval.addIntervall(actual._tokenstart, actual._tokenstart+actual._tokensize);
}
- if (interval.nextNotIgnored(actual._dataStart) < output_end)
+ // Remove possible empty data
+ int dstart = interval.nextNotIgnored(actual._dataStart);
+ while ((dstart < output_end) && (interval.par[dstart] == '{')) {
+ interval.addIntervall(dstart, dstart+1);
+ int dend = interval.findclosing(dstart+1, output_end);
+ interval.addIntervall(dend, dend+1);
+ dstart = interval.nextNotIgnored(dstart+1);
+ }
+ if (dstart < output_end)
interval.output(os, output_end);
interval.addIntervall(actual._tokenstart, end);
return nextKeyIdx;
else
result = m[m.size() - close_wildcards].first - m[0].first;
- size_t pos = m.position(0);
+ size_t pos = m.position(size_t(0));
// Ignore last closing characters
while (result > 0) {
if (str[pos+result-1] == '}')
// Compute the match length
int len = 1;
+ if (cur.pos() + len > cur.lastpos())
+ return 0;
if (match.opt.matchword) {
- if (cur.pos() + len > cur.lastpos())
- return 0;
LYXERR(Debug::FIND, "verifying unmatch with len = " << len);
while (cur.pos() + len <= cur.lastpos() && match(cur, len) <= 0) {
++len;
len = 0;
}
else {
- int minl = 1;
- int maxl = cur.lastpos() - cur.pos();
- // Greedy behaviour while matching regexps
- while (maxl > minl) {
- int actual_match = match(cur, len);
- if (actual_match == max_match) {
- maxl = len;
- len = (int)((maxl + minl)/2);
- }
- else if (actual_match < max_match) {
- minl = len + 1;
- len = (int)((maxl + minl)/2);
- }
- else {
- // cannot happen, but in case of
- LYXERR0("????");
- max_match = actual_match;
- }
- }
- }
+ int minl = 1;
+ int maxl = cur.lastpos() - cur.pos();
+ // Greedy behaviour while matching regexps
+ while (maxl > minl) {
+ int actual_match = match(cur, len);
+ if (actual_match >= max_match) {
+ // actual_match > max_match _can_ happen,
+ // if the search area splits
+ // some following word so that the regex
+ // (e.g. 'r.*r\b' matches 'r' from the middle of the
+ // splitted word)
+ // This means, the len value is too big
+ maxl = len;
+ len = (int)((maxl + minl)/2);
+ }
+ else {
+ // (actual_match < max_match)
+ minl = len + 1;
+ len = (int)((maxl + minl)/2);
+ }
+ }
+ }
return len;
}