mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-09 18:31:04 +00:00
AdvSearch - next patch from Tommaso.
http://www.mail-archive.com/lyx-devel@lists.lyx.org/msg146966.html git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@27938 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
d5f2772922
commit
fd6679bd34
@ -2448,6 +2448,29 @@ docstring Paragraph::asString(pos_type beg, pos_type end, int options) const
|
||||
}
|
||||
|
||||
|
||||
docstring Paragraph::stringify(pos_type beg, pos_type end, int options, OutputParams & runparams) const
|
||||
{
|
||||
odocstringstream os;
|
||||
|
||||
if (beg == 0
|
||||
&& options & AS_STR_LABEL
|
||||
&& !d->params_.labelString().empty())
|
||||
os << d->params_.labelString() << ' ';
|
||||
|
||||
for (pos_type i = beg; i < end; ++i) {
|
||||
char_type const c = d->text_[i];
|
||||
if (isPrintable(c) || c == '\t'
|
||||
|| (c == '\n' && options & AS_STR_NEWLINES))
|
||||
os.put(c);
|
||||
else if (c == META_INSET && options & AS_STR_INSETS) {
|
||||
getInset(i)->plaintext(os, runparams);
|
||||
}
|
||||
}
|
||||
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
void Paragraph::setInsetOwner(Inset const * inset)
|
||||
{
|
||||
d->inset_owner_ = inset;
|
||||
|
@ -124,6 +124,10 @@ public:
|
||||
docstring asString(pos_type beg, pos_type end,
|
||||
int options = AS_STR_NONE) const;
|
||||
|
||||
/// Extract only the explicitly visible text (without any formatting),
|
||||
/// descending into insets
|
||||
docstring stringify(pos_type beg, pos_type end, int options, OutputParams & runparams) const;
|
||||
|
||||
///
|
||||
void write(std::ostream &, BufferParams const &,
|
||||
depth_type & depth) const;
|
||||
|
@ -106,9 +106,15 @@ void FindAndReplace::findAdv(bool casesensitive,
|
||||
} else {
|
||||
ParIterator it = buffer.par_iterator_begin();
|
||||
ParIterator end = buffer.par_iterator_end();
|
||||
OutputParams runparams(&buffer.params().encoding());
|
||||
odocstringstream os;
|
||||
runparams.nice = true;
|
||||
runparams.flavor = OutputParams::LATEX;
|
||||
runparams.linelen = 100000; //lyxrc.plaintext_linelen;
|
||||
runparams.dryrun = true;
|
||||
for (; it != end; ++it) {
|
||||
LYXERR0("Adding to search string: '" << it->asString(false) << "'");
|
||||
searchString += it->asString(AS_STR_INSETS);
|
||||
searchString += it->stringify(pos_type(0), it->size(), AS_STR_INSETS, runparams);
|
||||
}
|
||||
}
|
||||
// lyxerr << "Searching for '" << to_utf8(searchString) << "'" << std::endl;
|
||||
|
168
src/lyxfind.cpp
168
src/lyxfind.cpp
@ -1,7 +1,7 @@
|
||||
/**
|
||||
* \file lyxfind.cpp
|
||||
* This file is part of LyX, the document processor.
|
||||
* Licence details can be found in the file COPYING.
|
||||
* License details can be found in the file COPYING.
|
||||
*
|
||||
* \author Lars Gullik Bjønnes
|
||||
* \author John Levon
|
||||
@ -43,8 +43,10 @@
|
||||
#include "support/docstream.h"
|
||||
#include "support/gettext.h"
|
||||
#include "support/lstrings.h"
|
||||
#include "support/lassert.h"
|
||||
|
||||
#include <boost/regex.hpp>
|
||||
#include <boost/next_prior.hpp>
|
||||
|
||||
using namespace std;
|
||||
using namespace lyx::support;
|
||||
@ -418,7 +420,7 @@ string apply_escapes(string s, Escapes const & escape_map)
|
||||
**/
|
||||
size_t find_matching_brace(string const & s, size_t pos)
|
||||
{
|
||||
BOOST_ASSERT(s[pos] == '{');
|
||||
LASSERT(s[pos] == '{', /* */);
|
||||
int open_braces = 1;
|
||||
for (++pos; pos < s.size(); ++pos) {
|
||||
if (s[pos] == '\\')
|
||||
@ -534,10 +536,14 @@ public:
|
||||
/** 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.
|
||||
**
|
||||
** @param at_begin
|
||||
** If set, then match is searched only against beginning of text starting at cur.
|
||||
** If unset, then match is searched anywhere in text starting at cur.
|
||||
**
|
||||
** @return
|
||||
** The length of the matching text, or zero if no match was found.
|
||||
**/
|
||||
int operator()(DocIterator const & cur, int len = -1) const;
|
||||
int operator()(DocIterator const & cur, int len = -1, bool at_begin = true) const;
|
||||
|
||||
public:
|
||||
/// buffer
|
||||
@ -564,6 +570,8 @@ private:
|
||||
string par_as_string;
|
||||
// regular expression to use for searching
|
||||
boost::regex regexp;
|
||||
// same as regexp, but prefixed with a ".*"
|
||||
boost::regex regexp2;
|
||||
// unmatched open braces in the search string/regexp
|
||||
int open_braces;
|
||||
// number of (.*?) subexpressions added at end of search regexp for closing
|
||||
@ -599,7 +607,7 @@ MatchStringAdv::MatchStringAdv(lyx::Buffer const & buf, FindAdvOptions const & o
|
||||
break;
|
||||
} while (true);
|
||||
LYXERR(Debug::DEBUG, "Open braces: " << open_braces);
|
||||
BOOST_ASSERT(braces_match(par_as_string.begin(), par_as_string.end(), open_braces));
|
||||
LASSERT(braces_match(par_as_string.begin(), par_as_string.end(), open_braces), /* */);
|
||||
LYXERR(Debug::DEBUG, "Built MatchStringAdv object: par_as_string = '" << par_as_string << "'");
|
||||
} else {
|
||||
par_as_string = escape_for_regex(par_as_string);
|
||||
@ -620,26 +628,35 @@ MatchStringAdv::MatchStringAdv(lyx::Buffer const & buf, FindAdvOptions const & o
|
||||
LYXERR(Debug::DEBUG, "par_as_string now is '" << par_as_string << "'");
|
||||
LYXERR(Debug::DEBUG, "Open braces: " << open_braces);
|
||||
LYXERR(Debug::DEBUG, "Close .*? : " << close_wildcards);
|
||||
BOOST_ASSERT(braces_match(par_as_string.begin(), par_as_string.end(), open_braces));
|
||||
LASSERT(braces_match(par_as_string.begin(), par_as_string.end(), open_braces), /* */);
|
||||
// Entered regexp must match at begin of searched string buffer
|
||||
par_as_string = string("\\`") + par_as_string;
|
||||
LYXERR(Debug::DEBUG, "Replaced text (to be used as regex): " << par_as_string);
|
||||
regexp = boost::regex(par_as_string);
|
||||
regexp2 = boost::regex(string(".*") + par_as_string);
|
||||
}
|
||||
}
|
||||
|
||||
int MatchStringAdv::operator()(DocIterator const & cur, int len) const
|
||||
|
||||
int MatchStringAdv::operator()(DocIterator const & cur, int len, bool at_begin) const
|
||||
{
|
||||
docstring docstr = stringifyFromForSearch(opt, buf, cur, len);
|
||||
docstring docstr = stringifyFromForSearch(opt, cur, len);
|
||||
LYXERR(Debug::DEBUG, "Matching against '" << lyx::to_utf8(docstr) << "'");
|
||||
string str = normalize(docstr);
|
||||
LYXERR(Debug::DEBUG, "After normalization: '" << str << "'");
|
||||
if (! opt.regexp) {
|
||||
if (str.substr(0, par_as_string.size()) == par_as_string)
|
||||
return par_as_string.size();
|
||||
if (at_begin) {
|
||||
if (str.substr(0, par_as_string.size()) == par_as_string)
|
||||
return par_as_string.size();
|
||||
} else {
|
||||
size_t pos = str.find(par_as_string);
|
||||
if (pos != string::npos)
|
||||
return par_as_string.size();
|
||||
}
|
||||
} else {
|
||||
// Try all possible regexp matches, until one that verifies the braces match test is found
|
||||
boost::sregex_iterator re_it(str.begin(), str.end(), regexp);
|
||||
boost::regex const *p_regexp = at_begin ? ®exp : ®exp2;
|
||||
boost::sregex_iterator re_it(str.begin(), str.end(), *p_regexp);
|
||||
boost::sregex_iterator re_it_end;
|
||||
for (; re_it != re_it_end; ++re_it) {
|
||||
boost::match_results<string::const_iterator> const & m = *re_it;
|
||||
@ -693,7 +710,16 @@ docstring stringifyFromCursor(DocIterator const & cur, int len)
|
||||
Paragraph const & par = cur.paragraph();
|
||||
// TODO what about searching beyond/across paragraph breaks ?
|
||||
// TODO Try adding a AS_STR_INSERTS as last arg
|
||||
return par.asString(cur.pos(), ( len == -1 || cur.pos() + len > int(par.size()) ) ? int(par.size()) : cur.pos() + len, AS_STR_INSETS);
|
||||
pos_type end = ( len == -1 || cur.pos() + len > int(par.size()) ) ? int(par.size()) : cur.pos() + len;
|
||||
OutputParams runparams(&cur.buffer()->params().encoding());
|
||||
odocstringstream os;
|
||||
runparams.nice = true;
|
||||
runparams.flavor = OutputParams::LATEX;
|
||||
runparams.linelen = 100000; //lyxrc.plaintext_linelen;
|
||||
// No side effect of file copying and image conversion
|
||||
runparams.dryrun = true;
|
||||
LYXERR(Debug::DEBUG, "Stringifying with cur: " << cur << ", from pos: " << cur.pos() << ", end: " << end);
|
||||
return par.stringify(cur.pos(), end, AS_STR_INSETS, runparams);
|
||||
} else if (cur.inMathed()) {
|
||||
odocstringstream os;
|
||||
CursorSlice cs = cur.top();
|
||||
@ -712,12 +738,13 @@ docstring stringifyFromCursor(DocIterator const & cur, int len)
|
||||
* if len is -1.
|
||||
*/
|
||||
|
||||
docstring latexifyFromCursor(Buffer const & buf, DocIterator const & cur, int len)
|
||||
docstring latexifyFromCursor(DocIterator const & cur, int len)
|
||||
{
|
||||
LYXERR(Debug::DEBUG, "Latexifying with len=" << len << " from cursor at pos: " << cur);
|
||||
LYXERR(Debug::DEBUG, " with cur.lastpost=" << cur.lastpos() << ", cur.lastrow="
|
||||
<< cur.lastrow() << ", cur.lastcol=" << cur.lastcol());
|
||||
BOOST_ASSERT(buf.isLatex());
|
||||
Buffer const & buf = *cur.buffer();
|
||||
LASSERT(buf.isLatex(), /* */);
|
||||
|
||||
TexRow texrow;
|
||||
odocstringstream ods;
|
||||
@ -795,13 +822,13 @@ int findAdvFinalize(DocIterator & cur, MatchStringAdv const & match)
|
||||
size_t d;
|
||||
DocIterator old_cur(cur.buffer());
|
||||
do {
|
||||
LYXERR(Debug::DEBUG, "Forwarding one step (searching for innermost match)");
|
||||
LYXERR(Debug::DEBUG, "Forwarding one step (searching for innermost match)");
|
||||
d = cur.depth();
|
||||
old_cur = cur;
|
||||
cur.forwardPos();
|
||||
} while (cur && cur.depth() > d && match(cur) > 0);
|
||||
cur = old_cur;
|
||||
BOOST_ASSERT(match(cur) > 0);
|
||||
LASSERT(match(cur) > 0, /* */);
|
||||
LYXERR(Debug::DEBUG, "Ok");
|
||||
|
||||
// Compute the match length
|
||||
@ -823,69 +850,104 @@ int findAdvFinalize(DocIterator & cur, MatchStringAdv const & match)
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
/// Finds forward
|
||||
int findForwardAdv(DocIterator & cur, MatchStringAdv const & match)
|
||||
{
|
||||
if (!cur)
|
||||
return 0;
|
||||
for (; cur; cur.forwardPos()) {
|
||||
// odocstringstream ods;
|
||||
// ods << _("Searching ... ")
|
||||
// << (cur.bottom().lastpit() - cur.bottom().pit()) * 100 / total;
|
||||
// cur.message(ods.str());
|
||||
if (match(cur))
|
||||
return findAdvFinalize(cur, match);
|
||||
}
|
||||
int wrap_answer;
|
||||
do {
|
||||
while (cur && !match(cur, -1, false)) {
|
||||
if (cur.pit() < cur.lastpit())
|
||||
cur.forwardPar();
|
||||
else {
|
||||
cur.forwardPos();
|
||||
}
|
||||
}
|
||||
for (; cur; cur.forwardPos()) {
|
||||
if (match(cur))
|
||||
return findAdvFinalize(cur, match);
|
||||
}
|
||||
wrap_answer = frontend::Alert::prompt(
|
||||
_("Wrap search ?"),
|
||||
_("End of document reached while searching forward\n"
|
||||
"\n"
|
||||
"Continue searching from beginning ?"),
|
||||
0, 1, _("&Yes"), _("&No"));
|
||||
cur.clear();
|
||||
cur.push_back(CursorSlice(match.buf.inset()));
|
||||
} while (wrap_answer == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/// Finds backwards
|
||||
int findBackwardsAdv(DocIterator & cur, MatchStringAdv const & match)
|
||||
{
|
||||
int findBackwardsAdv(DocIterator & cur, MatchStringAdv const & match) {
|
||||
// if (cur.pos() > 0 || cur.depth() > 0)
|
||||
// cur.backwardPos();
|
||||
DocIterator cur_orig(cur);
|
||||
if (match(cur_orig))
|
||||
findAdvFinalize(cur_orig, match);
|
||||
// int total = cur.bottom().pit() + 1;
|
||||
for (; cur; cur.backwardPos()) {
|
||||
// odocstringstream ods;
|
||||
// ods << _("Searching ... ") << (total - cur.bottom().pit()) * 100 / total;
|
||||
// cur.message(ods.str());
|
||||
if (match(cur)) {
|
||||
// Find the most backward consecutive match within same
|
||||
// paragraph while searching backwards.
|
||||
int pit = cur.pit();
|
||||
int old_len;
|
||||
DocIterator old_cur;
|
||||
int len = findAdvFinalize(cur, match);
|
||||
do {
|
||||
old_cur = cur;
|
||||
old_len = len;
|
||||
// int total = cur.bottom().pit() + 1;
|
||||
int wrap_answer;
|
||||
do {
|
||||
// TODO No ! così non va.
|
||||
bool pit_changed = false;
|
||||
while (cur && !match(cur, -1, false)) {
|
||||
if (cur.pit() > 0)
|
||||
--cur.pit();
|
||||
else {
|
||||
cur.backwardPos();
|
||||
LYXERR(Debug::DEBUG, "old_cur: " << old_cur
|
||||
<< ", old_len: " << len << ", cur: " << cur);
|
||||
} while (cur && cur.pit() == pit && match(cur)
|
||||
&& (len = findAdvFinalize(cur, match)) > old_len);
|
||||
cur = old_cur;
|
||||
len = old_len;
|
||||
LYXERR(Debug::DEBUG, "cur_orig : " << cur_orig);
|
||||
LYXERR(Debug::DEBUG, "cur : " << cur);
|
||||
if (cur != cur_orig)
|
||||
return len;
|
||||
if (cur)
|
||||
cur.pos() = 0;
|
||||
}
|
||||
pit_changed = true;
|
||||
}
|
||||
}
|
||||
if (cur && pit_changed)
|
||||
cur.pos() = cur.lastpos();
|
||||
for (; cur; cur.backwardPos()) {
|
||||
if (match(cur)) {
|
||||
// Find the most backward consecutive match within same paragraph while searching backwards.
|
||||
int pit = cur.pit();
|
||||
int old_len;
|
||||
DocIterator old_cur;
|
||||
int len = findAdvFinalize(cur, match);
|
||||
do {
|
||||
old_cur = cur;
|
||||
old_len = len;
|
||||
cur.backwardPos();
|
||||
LYXERR(Debug::DEBUG, "old_cur: " << old_cur << ", old_len=" << len << ", cur: " << cur);
|
||||
} while (cur && cur.pit() == pit && match(cur)
|
||||
&& (len = findAdvFinalize(cur, match)) > old_len);
|
||||
cur = old_cur;
|
||||
len = old_len;
|
||||
LYXERR(Debug::DEBUG, "cur_orig : " << cur_orig);
|
||||
LYXERR(Debug::DEBUG, "cur : " << cur);
|
||||
if (cur != cur_orig)
|
||||
return len;
|
||||
}
|
||||
}
|
||||
wrap_answer = frontend::Alert::prompt(
|
||||
_("Wrap search ?"),
|
||||
_("Beginning of document reached while searching backwards\n"
|
||||
"\n"
|
||||
"Continue searching from end ?"),
|
||||
0, 1, _("&Yes"), _("&No"));
|
||||
cur = doc_iterator_end(&match.buf);
|
||||
cur.backwardPos();
|
||||
} while (wrap_answer == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // anonym namespace
|
||||
|
||||
|
||||
docstring stringifyFromForSearch(FindAdvOptions const & opt, Buffer const & buf,
|
||||
docstring stringifyFromForSearch(FindAdvOptions const & opt,
|
||||
DocIterator const & cur, int len)
|
||||
{
|
||||
if (!opt.ignoreformat)
|
||||
return latexifyFromCursor(buf, cur, len);
|
||||
return latexifyFromCursor(cur, len);
|
||||
else
|
||||
return stringifyFromCursor(cur, len);
|
||||
}
|
||||
|
@ -68,22 +68,23 @@ bool findNextChange(BufferView * bv);
|
||||
|
||||
class FindAdvOptions {
|
||||
public:
|
||||
FindAdvOptions(
|
||||
docstring const & search,
|
||||
bool casesensitive,
|
||||
bool matchword,
|
||||
bool forward,
|
||||
bool expandmacros,
|
||||
bool ignoreformat,
|
||||
bool regexp);
|
||||
FindAdvOptions() {}
|
||||
docstring search;
|
||||
bool casesensitive;
|
||||
bool matchword;
|
||||
bool forward;
|
||||
bool expandmacros;
|
||||
bool ignoreformat;
|
||||
bool regexp;
|
||||
FindAdvOptions(
|
||||
docstring const & search,
|
||||
bool casesensitive,
|
||||
bool matchword,
|
||||
bool forward,
|
||||
bool expandmacros,
|
||||
bool ignoreformat,
|
||||
bool regexp
|
||||
);
|
||||
FindAdvOptions() { }
|
||||
docstring search;
|
||||
bool casesensitive;
|
||||
bool matchword;
|
||||
bool forward;
|
||||
bool expandmacros;
|
||||
bool ignoreformat;
|
||||
bool regexp;
|
||||
};
|
||||
|
||||
/// Write a FindAdvOptions instance to a stringstream
|
||||
@ -105,8 +106,10 @@ bool findAdv(BufferView * bv, FindAdvOptions const & opt);
|
||||
** This is useful for computing opt.search from the SearchAdvDialog controller (ControlSearchAdv).
|
||||
** Ideally, this should not be needed, and the opt.search field should become a Text const &.
|
||||
**/
|
||||
docstring stringifyFromForSearch(FindAdvOptions const & opt,
|
||||
Buffer const & buf, DocIterator const & cur, int len = -1);
|
||||
docstring stringifyFromForSearch(
|
||||
FindAdvOptions const & opt,
|
||||
DocIterator const & cur,
|
||||
int len = -1);
|
||||
|
||||
} // namespace lyx
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user