Refactor regex based selection code

This commit is contained in:
Maxime Coste 2017-03-03 23:43:54 +00:00
parent 31edff85c3
commit ed3c48057d

View File

@ -808,73 +808,70 @@ void select_buffer(SelectionList& selections)
selections = SelectionList{ buffer, target_eol({{0,0}, buffer.back_coord()}) }; selections = SelectionList{ buffer, target_eol({{0,0}, buffer.back_coord()}) };
} }
template<Direction direction> static RegexConstant::match_flag_type
static bool find_match_in_buffer(const Buffer& buffer, const BufferIterator pos, match_flags(const Buffer& buf, BufferIterator begin, BufferIterator end)
MatchResults<BufferIterator>& matches,
const Regex& ex, bool& wrapped)
{ {
wrapped = false; return match_flags(is_bol(begin.coord()), is_eol(buf, end.coord()),
if (direction == Forward) is_bow(buf, begin.coord()), is_eow(buf, end.coord()));
{ }
if (pos != buffer.end() and
regex_search(pos, buffer.end(), matches, ex, static bool find_next(const Buffer& buffer, BufferIterator pos,
match_flags(is_bol(pos.coord()), true, MatchResults<BufferIterator>& matches,
is_bow(buffer, pos.coord()), true))) const Regex& ex, bool& wrapped)
return true; {
wrapped = true; if (pos != buffer.end() and
return regex_search(buffer.begin(), buffer.end(), matches, ex); regex_search(pos, buffer.end(), matches, ex,
} match_flags(buffer, pos, buffer.end())))
else return true;
{ wrapped = true;
auto find_last_match = [&](const BufferIterator& pos) { return regex_search(buffer.begin(), buffer.end(), matches, ex,
MatchResults<BufferIterator> m; match_flags(buffer, buffer.begin(), buffer.end()));
const bool is_pos_eol = is_eol(buffer, pos.coord()); }
const bool is_pos_eow = is_eow(buffer, pos.coord());
auto begin = buffer.begin(); static bool find_prev(const Buffer& buffer, BufferIterator pos,
while (begin != pos and MatchResults<BufferIterator>& matches,
regex_search(begin, pos, m, ex, const Regex& ex, bool& wrapped)
match_flags(is_bol(begin.coord()), is_pos_eol, {
is_bow(buffer, begin.coord()), is_pos_eow))) auto find_last_match = [&](const BufferIterator& pos) {
{ MatchResults<BufferIterator> m;
begin = utf8::next(m[0].first, pos); const bool is_pos_eol = is_eol(buffer, pos.coord());
if (matches.empty() or m[0].second > matches[0].second) const bool is_pos_eow = is_eow(buffer, pos.coord());
matches.swap(m); auto begin = buffer.begin();
} while (begin != pos and
return not matches.empty(); regex_search(begin, pos, m, ex,
}; match_flags(is_bol(begin.coord()), is_pos_eol,
is_bow(buffer, begin.coord()), is_pos_eow)))
if (find_last_match(pos)) {
return true; begin = utf8::next(m[0].first, pos);
wrapped = true; if (matches.empty() or m[0].second > matches[0].second)
return find_last_match(buffer.end()); matches.swap(m);
} }
return not matches.empty();
};
if (find_last_match(pos))
return true;
wrapped = true;
return find_last_match(buffer.end());
} }
template bool find_match_in_buffer<Forward>(const Buffer&, const BufferIterator,
MatchResults<BufferIterator>&, const Regex&, bool&);
template bool find_match_in_buffer<Backward>(const Buffer&, const BufferIterator,
MatchResults<BufferIterator>&, const Regex&, bool&);
template<Direction direction> template<Direction direction>
Selection find_next_match(const Buffer& buffer, const Selection& sel, const Regex& regex, bool& wrapped) Selection find_next_match(const Buffer& buffer, const Selection& sel, const Regex& regex, bool& wrapped)
{ {
auto begin = buffer.iterator_at(direction == Backward ? sel.min() : sel.max());
auto end = begin;
CaptureList captures;
MatchResults<BufferIterator> matches; MatchResults<BufferIterator> matches;
bool found = false; auto pos = buffer.iterator_at(direction == Backward ? sel.min() : sel.max());
auto pos = direction == Forward ? utf8::next(begin, buffer.end()) : begin; wrapped = false;
if ((found = find_match_in_buffer<direction>(buffer, pos, matches, regex, wrapped))) const bool found = (direction == Forward) ?
{ find_next(buffer, utf8::next(pos, buffer.end()), matches, regex, wrapped)
begin = matches[0].first; : find_prev(buffer, pos, matches, regex, wrapped);
end = matches[0].second;
for (const auto& match : matches) if (not found or matches[0].first == buffer.end())
captures.push_back(buffer.string(match.first.coord(),
match.second.coord()));
}
if (not found or begin == buffer.end())
throw runtime_error(format("'{}': no matches found", regex.str())); throw runtime_error(format("'{}': no matches found", regex.str()));
CaptureList captures;
for (const auto& match : matches)
captures.push_back(buffer.string(match.first.coord(), match.second.coord()));
auto begin = matches[0].first, end = matches[0].second;
end = (begin == end) ? end : utf8::previous(end, begin); end = (begin == end) ? end : utf8::previous(end, begin);
if (direction == Backward) if (direction == Backward)
std::swap(begin, end); std::swap(begin, end);
@ -898,11 +895,8 @@ void select_all_matches(SelectionList& selections, const Regex& regex, int captu
{ {
auto sel_beg = buffer.iterator_at(sel.min()); auto sel_beg = buffer.iterator_at(sel.min());
auto sel_end = utf8::next(buffer.iterator_at(sel.max()), buffer.end()); auto sel_end = utf8::next(buffer.iterator_at(sel.max()), buffer.end());
const auto flags = match_flags(is_bol(sel_beg.coord()), RegexIt re_it(sel_beg, sel_end, regex,
is_eol(buffer, sel_end.coord()), match_flags(buffer, sel_beg, sel_end));
is_bow(buffer, sel_beg.coord()),
is_eow(buffer, sel_end.coord()));
RegexIt re_it(sel_beg, sel_end, regex, flags);
RegexIt re_end; RegexIt re_end;
for (; re_it != re_end; ++re_it) for (; re_it != re_end; ++re_it)
@ -945,12 +939,9 @@ void split_selections(SelectionList& selections, const Regex& regex, int capture
{ {
auto begin = buffer.iterator_at(sel.min()); auto begin = buffer.iterator_at(sel.min());
auto sel_end = utf8::next(buffer.iterator_at(sel.max()), buffer.end()); auto sel_end = utf8::next(buffer.iterator_at(sel.max()), buffer.end());
const auto flags = match_flags(is_bol(begin.coord()),
is_eol(buffer, sel_end.coord()),
is_bow(buffer, begin.coord()),
is_eow(buffer, sel_end.coord()));
RegexIt re_it(begin, sel_end, regex, flags); RegexIt re_it(begin, sel_end, regex,
match_flags(buffer, begin, sel_end));
RegexIt re_end; RegexIt re_end;
for (; re_it != re_end; ++re_it) for (; re_it != re_end; ++re_it)