Notify when searching for next match wraps around buffer

Fixes #215
This commit is contained in:
Maxime Coste 2016-02-29 13:50:18 +00:00
parent 9b70346a00
commit 1138264a83
2 changed files with 44 additions and 16 deletions

View File

@ -455,22 +455,34 @@ void insert_output(Context& context, NormalParams)
template<Direction direction, SelectMode mode> template<Direction direction, SelectMode mode>
void select_next_match(const Buffer& buffer, SelectionList& selections, void select_next_match(const Buffer& buffer, SelectionList& selections,
const Regex& regex) const Regex& regex, bool& main_wrapped)
{ {
const int main_index = selections.main_index();
bool wrapped = false;
if (mode == SelectMode::Replace) if (mode == SelectMode::Replace)
{ {
for (auto& sel : selections) for (int i = 0; i < selections.size(); ++i)
sel = keep_direction(find_next_match<direction>(buffer, sel, regex), sel); {
auto& sel = selections[i];
sel = keep_direction(find_next_match<direction>(buffer, sel, regex, wrapped), sel);
if (i == main_index)
main_wrapped = wrapped;
}
} }
if (mode == SelectMode::Extend) if (mode == SelectMode::Extend)
{ {
for (auto& sel : selections) for (int i = 0; i < selections.size(); ++i)
sel.merge_with(find_next_match<direction>(buffer, sel, regex)); {
auto& sel = selections[i];
sel.merge_with(find_next_match<direction>(buffer, sel, regex, wrapped));
if (i == main_index)
main_wrapped = wrapped;
}
} }
else if (mode == SelectMode::Append) else if (mode == SelectMode::Append)
{ {
auto sel = keep_direction( auto sel = keep_direction(
find_next_match<direction>(buffer, selections.main(), regex), find_next_match<direction>(buffer, selections.main(), regex, main_wrapped),
selections.main()); selections.main());
selections.push_back(std::move(sel)); selections.push_back(std::move(sel));
selections.set_main_index(selections.size() - 1); selections.set_main_index(selections.size() - 1);
@ -635,9 +647,10 @@ void search(Context& context, NormalParams params)
RegisterManager::instance()[reg] = ex.str(); RegisterManager::instance()[reg] = ex.str();
if (not ex.empty() and not ex.str().empty()) if (not ex.empty() and not ex.str().empty())
{ {
bool main_wrapped = false;
int c = count; int c = count;
do { do {
select_next_match<direction, mode>(context.buffer(), context.selections(), ex); select_next_match<direction, mode>(context.buffer(), context.selections(), ex, main_wrapped);
} while (--c > 0); } while (--c > 0);
} }
}); });
@ -651,9 +664,15 @@ void search_next(Context& context, NormalParams params)
if (not str.empty()) if (not str.empty())
{ {
Regex ex{str}; Regex ex{str};
bool main_wrapped = false;
do { do {
select_next_match<direction, mode>(context.buffer(), context.selections(), ex); bool wrapped = false;
select_next_match<direction, mode>(context.buffer(), context.selections(), ex, wrapped);
main_wrapped = main_wrapped or wrapped;
} while (--params.count > 0); } while (--params.count > 0);
if (main_wrapped)
context.print_status({"main selection search wrapped around buffer", get_face("Information")});
} }
else else
throw runtime_error("no search pattern"); throw runtime_error("no search pattern");

View File

@ -257,15 +257,24 @@ inline bool find_last_match(const Buffer& buffer, const BufferIterator& pos,
template<Direction direction> template<Direction direction>
bool find_match_in_buffer(const Buffer& buffer, const BufferIterator pos, bool find_match_in_buffer(const Buffer& buffer, const BufferIterator pos,
MatchResults<BufferIterator>& matches, MatchResults<BufferIterator>& matches,
const Regex& ex) const Regex& ex, bool& wrapped)
{ {
wrapped = false;
if (direction == Forward) if (direction == Forward)
return (regex_search(pos, buffer.end(), matches, ex, {
match_flags(is_bol(pos.coord()), true, true)) or if (regex_search(pos, buffer.end(), matches, ex,
regex_search(buffer.begin(), buffer.end(), matches, ex)); match_flags(is_bol(pos.coord()), true, true)))
return true;
wrapped = true;
return regex_search(buffer.begin(), buffer.end(), matches, ex);
}
else else
return (find_last_match(buffer, pos, matches, ex) or {
find_last_match(buffer, buffer.end(), matches, ex)); if (find_last_match(buffer, pos, matches, ex))
return true;
wrapped = true;
return find_last_match(buffer, buffer.end(), matches, ex);
}
} }
inline BufferIterator ensure_char_start(const Buffer& buffer, const BufferIterator& it) inline BufferIterator ensure_char_start(const Buffer& buffer, const BufferIterator& it)
@ -275,7 +284,7 @@ inline BufferIterator ensure_char_start(const Buffer& buffer, const BufferIterat
} }
template<Direction direction> template<Direction direction>
Selection find_next_match(const Buffer& buffer, const Selection& sel, const Regex& regex) 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 begin = buffer.iterator_at(direction == Backward ? sel.min() : sel.max());
auto end = begin; auto end = begin;
@ -284,7 +293,7 @@ Selection find_next_match(const Buffer& buffer, const Selection& sel, const Rege
MatchResults<BufferIterator> matches; MatchResults<BufferIterator> matches;
bool found = false; bool found = false;
auto pos = direction == Forward ? utf8::next(begin, buffer.end()) : begin; auto pos = direction == Forward ? utf8::next(begin, buffer.end()) : begin;
if ((found = find_match_in_buffer<direction>(buffer, pos, matches, regex))) if ((found = find_match_in_buffer<direction>(buffer, pos, matches, regex, wrapped)))
{ {
begin = ensure_char_start(buffer, matches[0].first); begin = ensure_char_start(buffer, matches[0].first);
end = ensure_char_start(buffer, matches[0].second); end = ensure_char_start(buffer, matches[0].second);