diff options
| author | Maxime Coste <mawww@kakoune.org> | 2019-05-13 17:33:18 +1000 |
|---|---|---|
| committer | Maxime Coste <mawww@kakoune.org> | 2019-05-13 17:34:43 +1000 |
| commit | 91386a535ccecc1d5d9b0fc27223f8d9006750e3 (patch) | |
| tree | 3c63d1a2788373174cc120467fed52f1684906cb /src | |
| parent | 3114995857d9ca8a255e04f0dd3582f93e547eeb (diff) | |
Support discarding selections in exec/eval -itersel
Only fail if all selections are discarded.
Fixes #2841
Diffstat (limited to 'src')
| -rw-r--r-- | src/commands.cc | 30 | ||||
| -rw-r--r-- | src/normal.cc | 8 | ||||
| -rw-r--r-- | src/normal.hh | 6 |
3 files changed, 31 insertions, 13 deletions
diff --git a/src/commands.cc b/src/commands.cc index 51adb80c..b1fe3580 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -1782,26 +1782,38 @@ void context_wrap(const ParametersParser& parser, Context& context, StringView d Vector<Selection> new_sels; size_t main = 0; size_t timestamp = c.buffer().timestamp(); + bool one_selection_succeeded = false; for (auto& sel : sels) { c.selections_write_only() = SelectionList{sels.buffer(), sel, sels.timestamp()}; c.selections().update(); - func(parser, c); - - if (not draft) + try { + func(parser, c); + one_selection_succeeded = true; + if (&sels.buffer() != &c.buffer()) throw runtime_error("buffer has changed while iterating on selections"); - update_selections(new_sels, main, c.buffer(), timestamp); - timestamp = c.buffer().timestamp(); - if (&sel == &sels.main()) - main = new_sels.size() + c.selections().main_index(); + if (not draft) + { + update_selections(new_sels, main, c.buffer(), timestamp); + timestamp = c.buffer().timestamp(); + if (&sel == &sels.main()) + main = new_sels.size() + c.selections().main_index(); - const auto middle = new_sels.insert(new_sels.end(), c.selections().begin(), c.selections().end()); - std::inplace_merge(new_sels.begin(), middle, new_sels.end(), compare_selections); + const auto middle = new_sels.insert(new_sels.end(), c.selections().begin(), c.selections().end()); + std::inplace_merge(new_sels.begin(), middle, new_sels.end(), compare_selections); + } } + catch (no_selections_remaining&) {} + } + + if (not one_selection_succeeded) + { + c.selections_write_only() = std::move(sels); + throw no_selections_remaining{}; } if (not draft) diff --git a/src/normal.cc b/src/normal.cc index 1101302b..565f0472 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -113,7 +113,7 @@ void select(Context& context, T func) } if (to_remove.size() == selections.size()) - throw runtime_error{"no selections remaining"}; + throw no_selections_remaining{}; for (auto& i : to_remove | reverse()) selections.remove(i); } @@ -1135,7 +1135,7 @@ void keep(Context& context, NormalParams params) keep.push_back(sel); } if (keep.empty()) - throw runtime_error("no selections remaining"); + throw no_selections_remaining{}; context.selections_write_only() = std::move(keep); }); } @@ -1168,7 +1168,7 @@ void keep_pipe(Context& context, NormalParams) } } if (keep.empty()) - throw runtime_error("no selections remaining"); + throw no_selections_remaining{}; if (new_main == -1) new_main = keep.size() - 1; context.selections_write_only().set(std::move(keep), new_main); @@ -1775,7 +1775,7 @@ void trim_selections(Context& context, NormalParams) } if (to_remove.size() == selections.size()) - throw runtime_error{"no selections remaining"}; + throw no_selections_remaining{}; for (auto& i : to_remove | reverse()) selections.remove(i); } diff --git a/src/normal.hh b/src/normal.hh index 10ee5ffa..e0eb8477 100644 --- a/src/normal.hh +++ b/src/normal.hh @@ -5,12 +5,18 @@ #include "keys.hh" #include "keymap_manager.hh" #include "string.hh" +#include "exception.hh" namespace Kakoune { class Context; +struct no_selections_remaining : runtime_error +{ + no_selections_remaining() : runtime_error("no selections remaining") {} +}; + struct NormalParams { int count; |
