diff options
| author | Maxime Coste <mawww@kakoune.org> | 2017-03-03 20:12:52 +0000 |
|---|---|---|
| committer | Maxime Coste <mawww@kakoune.org> | 2017-03-03 20:17:11 +0000 |
| commit | ddc5e958e6df7f1e94dfded5d7670433a23615f2 (patch) | |
| tree | fd94c78ec528d4da5c5103b984fdc48f62e33a82 /src/normal.cc | |
| parent | 6759511b9eb0acd066350f63e0112daf56c501f2 (diff) | |
Return an optional selection in most selectors, fail rather than keep current
Instead of returning the current selection when a selector fails, return
an empty Optional<Selection>. That means object selections will now
remove the selections that dont match the object.
Diffstat (limited to 'src/normal.cc')
| -rw-r--r-- | src/normal.cc | 42 |
1 files changed, 29 insertions, 13 deletions
diff --git a/src/normal.cc b/src/normal.cc index 4a6588c6..ce588bb2 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -40,33 +40,49 @@ void select(Context& context, T func) if (mode == SelectMode::Append) { auto& sel = selections.main(); - auto res = func(buffer, sel); - if (res.captures().empty()) - res.captures() = sel.captures(); - selections.push_back(res); - selections.set_main_index(selections.size() - 1); + if (auto res = func(buffer, sel)) + { + if (res->captures().empty()) + res->captures() = sel.captures(); + selections.push_back(std::move(*res)); + selections.set_main_index(selections.size() - 1); + } } else { - for (auto& sel : selections) + Vector<int> to_remove; + for (int i = 0; i < (int)selections.size(); ++i) { + auto& sel = selections[i]; auto res = func(buffer, sel); + if (not res) + { + to_remove.push_back(i); + continue; + } + if (mode == SelectMode::Extend) - sel.merge_with(res); + sel.merge_with(*res); else { - sel.anchor() = res.anchor(); - sel.cursor() = res.cursor(); + sel.anchor() = res->anchor(); + sel.cursor() = res->cursor(); } - if (not res.captures().empty()) - sel.captures() = std::move(res.captures()); + if (not res->captures().empty()) + sel.captures() = std::move(res->captures()); } + + if (to_remove.size() == selections.size()) + throw runtime_error{"no selections remaining"}; + for (auto& i : to_remove | reverse()) + selections.remove(i); } + selections.sort_and_merge_overlapping(); selections.check_invariant(); } -template<SelectMode mode, Selection (*func)(const Buffer&, const Selection&)> +template<SelectMode mode, Optional<Selection> (*func)(const Buffer&, const Selection&)> void select(Context& context, NormalParams) { select<mode>(context, func); @@ -1053,7 +1069,7 @@ void select_object(Context& context, NormalParams params) static constexpr struct ObjectType { Codepoint key; - Selection (*func)(const Buffer&, const Selection&, int, ObjectFlags); + Optional<Selection> (*func)(const Buffer&, const Selection&, int, ObjectFlags); } selectors[] = { { 'w', select_word<Word> }, { 'W', select_word<WORD> }, |
