From 243cfbc4aeb6bd0cccf185a68e926c225fd14af7 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Sat, 19 May 2018 14:02:11 +1000 Subject: [PATCH] Fix behaviour of extending to next match when wrapping If the search wraps to get to next match, drop that selection when extending. --- src/normal.cc | 56 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 43 insertions(+), 13 deletions(-) diff --git a/src/normal.cc b/src/normal.cc index aa7cef98..6db2b4bb 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -804,6 +804,45 @@ void regex_prompt(Context& context, String prompt, String default_regex, T func) }); } +template +void select_next_matches(Context& context, const Regex& regex, int count) +{ + auto& selections = context.selections(); + do { + bool wrapped = false; + for (auto& sel : selections) + sel = keep_direction(find_next_match(context, sel, regex, wrapped), sel); + selections.sort_and_merge_overlapping(); + } while (--count > 0); +} + +template +void extend_to_next_matches(Context& context, const Regex& regex, int count) +{ + Vector new_sels; + auto& selections = context.selections(); + do { + bool wrapped = false; + size_t main_index = selections.main_index(); + for (auto& sel : selections) + { + auto new_sel = find_next_match(context, sel, regex, wrapped); + if (not wrapped) + { + new_sels.push_back(sel); + merge_selections(new_sels.back(), new_sel); + } + else if (new_sels.size() <= main_index) + --main_index; + } + if (new_sels.empty()) + throw runtime_error{"All selections wrapped"}; + + selections.set(std::move(new_sels), main_index); + new_sels.clear(); + } while (--count > 0); +} + template void search(Context& context, NormalParams params) { @@ -831,19 +870,10 @@ void search(Context& context, NormalParams params) if (regex.empty() or regex.str().empty()) return; - int c = count; - auto& selections = context.selections(); - do { - bool wrapped = false; - for (auto& sel : selections) - { - if (mode == SelectMode::Replace) - sel = keep_direction(find_next_match(context, sel, regex, wrapped), sel); - if (mode == SelectMode::Extend) - merge_selections(sel, find_next_match(context, sel, regex, wrapped)); - } - selections.sort_and_merge_overlapping(); - } while (--c > 0); + if (mode == SelectMode::Extend) + extend_to_next_matches(context, regex, count); + else + select_next_matches(context, regex, count); }); }