diff --git a/src/normal.cc b/src/normal.cc index 009a2224..54b062c1 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -704,26 +704,28 @@ void use_selection_as_search_pattern(Context& context, NormalParams params) void select_regex(Context& context, NormalParams params) { const char reg = to_lower(params.reg ? params.reg : '/'); - regex_prompt(context, "select:", [reg](Regex ex, PromptEvent event, Context& context) { + unsigned capture = (unsigned)params.count; + regex_prompt(context, "select:", [reg, capture](Regex ex, PromptEvent event, Context& context) { if (ex.empty()) ex = Regex{context.main_sel_register_value(reg)}; else if (event == PromptEvent::Validate) RegisterManager::instance()[reg] = ex.str(); if (not ex.empty() and not ex.str().empty()) - select_all_matches(context.selections(), ex); + select_all_matches(context.selections(), ex, capture); }); } void split_regex(Context& context, NormalParams params) { const char reg = to_lower(params.reg ? params.reg : '/'); - regex_prompt(context, "split:", [reg](Regex ex, PromptEvent event, Context& context) { + unsigned capture = (unsigned)params.count; + regex_prompt(context, "split:", [reg, capture](Regex ex, PromptEvent event, Context& context) { if (ex.empty()) ex = Regex{context.main_sel_register_value(reg)}; else if (event == PromptEvent::Validate) RegisterManager::instance()[reg] = ex.str(); if (not ex.empty() and not ex.str().empty()) - split_selections(context.selections(), ex); + split_selections(context.selections(), ex, capture); }); } diff --git a/src/selectors.cc b/src/selectors.cc index 524ff9e1..c86d2749 100644 --- a/src/selectors.cc +++ b/src/selectors.cc @@ -560,8 +560,12 @@ void select_buffer(SelectionList& selections) using RegexIt = RegexIterator; -void select_all_matches(SelectionList& selections, const Regex& regex) +void select_all_matches(SelectionList& selections, const Regex& regex, unsigned capture) { + const unsigned mark_count = regex.mark_count(); + if (capture > mark_count) + throw runtime_error("invalid capture number"); + Vector result; auto& buffer = selections.buffer(); for (auto& sel : selections) @@ -570,13 +574,12 @@ void select_all_matches(SelectionList& selections, const Regex& regex) RegexIt re_it(buffer.iterator_at(sel.min()), sel_end, regex); RegexIt re_end; - const unsigned mark_count = regex.mark_count(); for (; re_it != re_end; ++re_it) { - auto begin = ensure_char_start(buffer, (*re_it)[0].first); + auto begin = ensure_char_start(buffer, (*re_it)[capture].first); if (begin == sel_end) continue; - auto end = ensure_char_start(buffer, (*re_it)[0].second); + auto end = ensure_char_start(buffer, (*re_it)[capture].second); CaptureList captures; captures.reserve(mark_count); @@ -598,8 +601,11 @@ void select_all_matches(SelectionList& selections, const Regex& regex) selections = SelectionList{buffer, std::move(result)}; } -void split_selections(SelectionList& selections, const Regex& regex) +void split_selections(SelectionList& selections, const Regex& regex, unsigned capture) { + if (capture > regex.mark_count()) + throw runtime_error("invalid capture number"); + Vector result; auto& buffer = selections.buffer(); auto buf_end = buffer.end(); @@ -612,13 +618,13 @@ void split_selections(SelectionList& selections, const Regex& regex) for (; re_it != re_end; ++re_it) { - BufferIterator end = (*re_it)[0].first; + BufferIterator end = (*re_it)[capture].first; if (end == buf_end) continue; end = ensure_char_start(buffer, end); result.push_back(keep_direction({ begin.coord(), (begin == end) ? end.coord() : utf8::previous(end, begin).coord() }, sel)); - begin = ensure_char_start(buffer, (*re_it)[0].second); + begin = ensure_char_start(buffer, (*re_it)[capture].second); } if (begin.coord() <= sel.max()) result.push_back(keep_direction({ begin.coord(), sel.max() }, sel)); diff --git a/src/selectors.hh b/src/selectors.hh index 7809344f..fff025fc 100644 --- a/src/selectors.hh +++ b/src/selectors.hh @@ -292,8 +292,8 @@ Selection find_next_match(const Buffer& buffer, const Selection& sel, const Rege return {begin.coord(), end.coord(), std::move(captures)}; } -void select_all_matches(SelectionList& selections, const Regex& regex); -void split_selections(SelectionList& selections, const Regex& separator_regex); +void select_all_matches(SelectionList& selections, const Regex& regex, unsigned capture = 0); +void split_selections(SelectionList& selections, const Regex& separator_regex, unsigned capture = 0); struct MatchingPair { Codepoint opening, closing; }; Selection select_surrounding(const Buffer& buffer, const Selection& selection,