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); }); }