Support discarding selections in exec/eval -itersel

Only fail if all selections are discarded.
Fixes #2841
This commit is contained in:
Maxime Coste 2019-05-13 17:33:18 +10:00
parent 3114995857
commit 91386a535c
6 changed files with 38 additions and 13 deletions

View File

@ -1782,26 +1782,38 @@ void context_wrap(const ParametersParser& parser, Context& context, StringView d
Vector<Selection> new_sels; Vector<Selection> new_sels;
size_t main = 0; size_t main = 0;
size_t timestamp = c.buffer().timestamp(); size_t timestamp = c.buffer().timestamp();
bool one_selection_succeeded = false;
for (auto& sel : sels) for (auto& sel : sels)
{ {
c.selections_write_only() = SelectionList{sels.buffer(), sel, sels.timestamp()}; c.selections_write_only() = SelectionList{sels.buffer(), sel, sels.timestamp()};
c.selections().update(); c.selections().update();
func(parser, c); try
if (not draft)
{ {
func(parser, c);
one_selection_succeeded = true;
if (&sels.buffer() != &c.buffer()) if (&sels.buffer() != &c.buffer())
throw runtime_error("buffer has changed while iterating on selections"); throw runtime_error("buffer has changed while iterating on selections");
update_selections(new_sels, main, c.buffer(), timestamp); if (not draft)
timestamp = c.buffer().timestamp(); {
if (&sel == &sels.main()) update_selections(new_sels, main, c.buffer(), timestamp);
main = new_sels.size() + c.selections().main_index(); 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()); 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); 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) if (not draft)

View File

@ -113,7 +113,7 @@ void select(Context& context, T func)
} }
if (to_remove.size() == selections.size()) if (to_remove.size() == selections.size())
throw runtime_error{"no selections remaining"}; throw no_selections_remaining{};
for (auto& i : to_remove | reverse()) for (auto& i : to_remove | reverse())
selections.remove(i); selections.remove(i);
} }
@ -1135,7 +1135,7 @@ void keep(Context& context, NormalParams params)
keep.push_back(sel); keep.push_back(sel);
} }
if (keep.empty()) if (keep.empty())
throw runtime_error("no selections remaining"); throw no_selections_remaining{};
context.selections_write_only() = std::move(keep); context.selections_write_only() = std::move(keep);
}); });
} }
@ -1168,7 +1168,7 @@ void keep_pipe(Context& context, NormalParams)
} }
} }
if (keep.empty()) if (keep.empty())
throw runtime_error("no selections remaining"); throw no_selections_remaining{};
if (new_main == -1) if (new_main == -1)
new_main = keep.size() - 1; new_main = keep.size() - 1;
context.selections_write_only().set(std::move(keep), new_main); 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()) if (to_remove.size() == selections.size())
throw runtime_error{"no selections remaining"}; throw no_selections_remaining{};
for (auto& i : to_remove | reverse()) for (auto& i : to_remove | reverse())
selections.remove(i); selections.remove(i);
} }

View File

@ -5,12 +5,18 @@
#include "keys.hh" #include "keys.hh"
#include "keymap_manager.hh" #include "keymap_manager.hh"
#include "string.hh" #include "string.hh"
#include "exception.hh"
namespace Kakoune namespace Kakoune
{ {
class Context; class Context;
struct no_selections_remaining : runtime_error
{
no_selections_remaining() : runtime_error("no selections remaining") {}
};
struct NormalParams struct NormalParams
{ {
int count; int count;

View File

@ -0,0 +1 @@
:exec -itersel <lt>a-k>ba<lt>ret><ret>d

View File

@ -0,0 +1,3 @@
%(foo)
%(bar)
%(baz)

View File

@ -0,0 +1,3 @@
foo