mirror of
https://github.com/mawww/kakoune.git
synced 2024-12-24 20:13:00 +03:00
Tolerate restoring invalid coordinates from register
Clamp those selection after updating them to the current timestamp Fixes #2078
This commit is contained in:
parent
ed123a2cc9
commit
124a5d4905
@ -1734,11 +1734,22 @@ SelectionList read_selections_from_register(char reg, Context& context)
|
||||
const auto desc = content[0] | split<StringView>('@') | static_gather<error, 3>();
|
||||
Buffer& buffer = BufferManager::instance().get_buffer(desc[0]);
|
||||
const size_t timestamp = str_to_int(desc[1]);
|
||||
const size_t main = str_to_int(desc[2]);
|
||||
size_t main = str_to_int(desc[2]);
|
||||
|
||||
if (timestamp > buffer.timestamp())
|
||||
throw runtime_error{"register '{}' refers to an invalid timestamp"};
|
||||
|
||||
auto sels = content | skip(1) | transform(selection_from_string) | gather<Vector<Selection>>();
|
||||
sort_selections(sels, main);
|
||||
merge_overlapping_selections(sels, main);
|
||||
if (timestamp < buffer.timestamp())
|
||||
update_selections(sels, main, buffer, timestamp);
|
||||
else
|
||||
clamp_selections(sels, buffer);
|
||||
|
||||
return {SelectionList::UnsortedTag{}, buffer, std::move(sels), timestamp, main};
|
||||
SelectionList res{buffer, std::move(sels)};
|
||||
res.set_main_index(main);
|
||||
return res;
|
||||
}
|
||||
|
||||
enum class CombineOp
|
||||
@ -2012,9 +2023,7 @@ void move_cursor(Context& context, NormalParams params)
|
||||
sel.anchor() = mode == SelectMode::Extend ? sel.anchor() : cursor;
|
||||
sel.cursor() = cursor;
|
||||
}
|
||||
selections.sort();
|
||||
|
||||
selections.merge_overlapping();
|
||||
selections.sort_and_merge_overlapping();
|
||||
}
|
||||
|
||||
void select_whole_buffer(Context& context, NormalParams)
|
||||
|
@ -212,6 +212,12 @@ static void clamp(Selection& sel, const Buffer& buffer)
|
||||
sel.cursor() = buffer.clamp(sel.cursor());
|
||||
}
|
||||
|
||||
void clamp_selections(Vector<Selection>& selections, const Buffer& buffer)
|
||||
{
|
||||
for (auto& sel : selections)
|
||||
clamp(sel, buffer);
|
||||
}
|
||||
|
||||
void update_selections(Vector<Selection>& selections, size_t& main, Buffer& buffer, size_t timestamp)
|
||||
{
|
||||
if (timestamp == buffer.timestamp())
|
||||
@ -286,30 +292,41 @@ void SelectionList::check_invariant() const
|
||||
#endif
|
||||
}
|
||||
|
||||
void SelectionList::sort()
|
||||
void sort_selections(Vector<Selection>& selections, size_t& main_index)
|
||||
{
|
||||
if (size() == 1)
|
||||
if (selections.size() == 1)
|
||||
return;
|
||||
|
||||
const auto& main = this->main();
|
||||
const auto& main = selections[main_index];
|
||||
const auto main_begin = main.min();
|
||||
m_main = std::count_if(begin(), end(), [&](const Selection& sel) {
|
||||
auto begin = sel.min();
|
||||
if (begin == main_begin)
|
||||
return &sel < &main;
|
||||
else
|
||||
return begin < main_begin;
|
||||
});
|
||||
std::stable_sort(begin(), end(), compare_selections);
|
||||
main_index = std::count_if(selections.begin(), selections.end(),
|
||||
[&](const Selection& sel) {
|
||||
auto begin = sel.min();
|
||||
if (begin == main_begin)
|
||||
return &sel < &main;
|
||||
else
|
||||
return begin < main_begin;
|
||||
});
|
||||
std::stable_sort(selections.begin(), selections.end(), compare_selections);
|
||||
}
|
||||
|
||||
void merge_overlapping_selections(Vector<Selection>& selections, size_t& main_index)
|
||||
{
|
||||
if (selections.size() == 1)
|
||||
return;
|
||||
|
||||
selections.erase(Kakoune::merge_overlapping(selections.begin(), selections.end(),
|
||||
main_index, overlaps), selections.end());
|
||||
}
|
||||
|
||||
void SelectionList::sort()
|
||||
{
|
||||
sort_selections(m_selections, m_main);
|
||||
}
|
||||
|
||||
void SelectionList::merge_overlapping()
|
||||
{
|
||||
if (size() == 1)
|
||||
return;
|
||||
|
||||
m_selections.erase(Kakoune::merge_overlapping(begin(), end(),
|
||||
m_main, overlaps), end());
|
||||
merge_overlapping_selections(m_selections, m_main);
|
||||
}
|
||||
|
||||
void SelectionList::merge_consecutive()
|
||||
|
@ -65,6 +65,10 @@ inline bool overlaps(const Selection& lhs, const Selection& rhs)
|
||||
void update_selections(Vector<Selection>& selections, size_t& main,
|
||||
Buffer& buffer, size_t timestamp);
|
||||
|
||||
void sort_selections(Vector<Selection>& selections, size_t& main);
|
||||
void merge_overlapping_selections(Vector<Selection>& selections, size_t& main);
|
||||
void clamp_selections(Vector<Selection>& sel, const Buffer& buffer);
|
||||
|
||||
enum class InsertMode : unsigned
|
||||
{
|
||||
Insert,
|
||||
|
@ -0,0 +1 @@
|
||||
ifoo<esc>ibar<esc>:set-register ^ <c-r>%@1@0 100.100,100.100<ret>z
|
@ -0,0 +1 @@
|
||||
|
@ -0,0 +1 @@
|
||||
1.7,1.7
|
Loading…
Reference in New Issue
Block a user