From 1138264a833bb8c9463836e5e6490012962bae6b Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Mon, 29 Feb 2016 13:50:18 +0000 Subject: [PATCH] Notify when searching for next match wraps around buffer Fixes #215 --- src/normal.cc | 35 +++++++++++++++++++++++++++-------- src/selectors.hh | 25 +++++++++++++++++-------- 2 files changed, 44 insertions(+), 16 deletions(-) diff --git a/src/normal.cc b/src/normal.cc index 81a337dd..7b6b84d9 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -455,22 +455,34 @@ void insert_output(Context& context, NormalParams) template 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) { - for (auto& sel : selections) - sel = keep_direction(find_next_match(buffer, sel, regex), sel); + for (int i = 0; i < selections.size(); ++i) + { + auto& sel = selections[i]; + sel = keep_direction(find_next_match(buffer, sel, regex, wrapped), sel); + if (i == main_index) + main_wrapped = wrapped; + } } if (mode == SelectMode::Extend) { - for (auto& sel : selections) - sel.merge_with(find_next_match(buffer, sel, regex)); + for (int i = 0; i < selections.size(); ++i) + { + auto& sel = selections[i]; + sel.merge_with(find_next_match(buffer, sel, regex, wrapped)); + if (i == main_index) + main_wrapped = wrapped; + } } else if (mode == SelectMode::Append) { auto sel = keep_direction( - find_next_match(buffer, selections.main(), regex), + find_next_match(buffer, selections.main(), regex, main_wrapped), selections.main()); selections.push_back(std::move(sel)); selections.set_main_index(selections.size() - 1); @@ -635,9 +647,10 @@ void search(Context& context, NormalParams params) RegisterManager::instance()[reg] = ex.str(); if (not ex.empty() and not ex.str().empty()) { + bool main_wrapped = false; int c = count; do { - select_next_match(context.buffer(), context.selections(), ex); + select_next_match(context.buffer(), context.selections(), ex, main_wrapped); } while (--c > 0); } }); @@ -651,9 +664,15 @@ void search_next(Context& context, NormalParams params) if (not str.empty()) { Regex ex{str}; + bool main_wrapped = false; do { - select_next_match(context.buffer(), context.selections(), ex); + bool wrapped = false; + select_next_match(context.buffer(), context.selections(), ex, wrapped); + main_wrapped = main_wrapped or wrapped; } while (--params.count > 0); + + if (main_wrapped) + context.print_status({"main selection search wrapped around buffer", get_face("Information")}); } else throw runtime_error("no search pattern"); diff --git a/src/selectors.hh b/src/selectors.hh index dc28dfd8..12ec7491 100644 --- a/src/selectors.hh +++ b/src/selectors.hh @@ -257,15 +257,24 @@ inline bool find_last_match(const Buffer& buffer, const BufferIterator& pos, template bool find_match_in_buffer(const Buffer& buffer, const BufferIterator pos, MatchResults& matches, - const Regex& ex) + const Regex& ex, bool& wrapped) { + wrapped = false; if (direction == Forward) - return (regex_search(pos, buffer.end(), matches, ex, - match_flags(is_bol(pos.coord()), true, true)) or - regex_search(buffer.begin(), buffer.end(), matches, ex)); + { + if (regex_search(pos, 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 - 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) @@ -275,7 +284,7 @@ inline BufferIterator ensure_char_start(const Buffer& buffer, const BufferIterat } template -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 end = begin; @@ -284,7 +293,7 @@ Selection find_next_match(const Buffer& buffer, const Selection& sel, const Rege MatchResults matches; bool found = false; auto pos = direction == Forward ? utf8::next(begin, buffer.end()) : begin; - if ((found = find_match_in_buffer(buffer, pos, matches, regex))) + if ((found = find_match_in_buffer(buffer, pos, matches, regex, wrapped))) { begin = ensure_char_start(buffer, matches[0].first); end = ensure_char_start(buffer, matches[0].second);