Editor: tweak behaviour on undo/redo when selecting modified ranges
This commit is contained in:
parent
564cfb084e
commit
33740d06ee
|
@ -128,31 +128,11 @@ static bool compare_selections(const Selection& lhs, const Selection& rhs)
|
||||||
return lhs.begin() < rhs.begin();
|
return lhs.begin() < rhs.begin();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool already_sorted = false>
|
template<typename OverlapsFunc>
|
||||||
void sort_and_merge_overlapping(SelectionList& selections, size_t& main_selection)
|
void merge_overlapping(SelectionList& selections, size_t& main_selection,
|
||||||
|
OverlapsFunc overlaps)
|
||||||
{
|
{
|
||||||
if (selections.size() == 1)
|
kak_assert(std::is_sorted(selections.begin(), selections.end(), compare_selections));
|
||||||
return;
|
|
||||||
|
|
||||||
if (already_sorted)
|
|
||||||
{
|
|
||||||
kak_assert(std::is_sorted(selections.begin(), selections.end(), compare_selections));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
const auto& main = selections[main_selection];
|
|
||||||
const auto main_begin = main.begin();
|
|
||||||
main_selection = std::count_if(selections.begin(), selections.end(),
|
|
||||||
[&](const Selection& sel) {
|
|
||||||
auto begin = sel.begin();
|
|
||||||
if (begin == main_begin)
|
|
||||||
return &sel < &main;
|
|
||||||
else
|
|
||||||
return sel.begin() < main_begin;
|
|
||||||
});
|
|
||||||
std::stable_sort(selections.begin(), selections.end(), compare_selections);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i+1 < selections.size() and selections.size() > 1;)
|
for (size_t i = 0; i+1 < selections.size() and selections.size() > 1;)
|
||||||
{
|
{
|
||||||
if (overlaps(selections[i], selections[i+1]))
|
if (overlaps(selections[i], selections[i+1]))
|
||||||
|
@ -167,6 +147,26 @@ void sort_and_merge_overlapping(SelectionList& selections, size_t& main_selectio
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sort_and_merge_overlapping(SelectionList& selections, size_t& main_selection)
|
||||||
|
{
|
||||||
|
if (selections.size() == 1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto& main = selections[main_selection];
|
||||||
|
const auto main_begin = main.begin();
|
||||||
|
main_selection = std::count_if(selections.begin(), selections.end(),
|
||||||
|
[&](const Selection& sel) {
|
||||||
|
auto begin = sel.begin();
|
||||||
|
if (begin == main_begin)
|
||||||
|
return &sel < &main;
|
||||||
|
else
|
||||||
|
return sel.begin() < main_begin;
|
||||||
|
});
|
||||||
|
std::stable_sort(selections.begin(), selections.end(), compare_selections);
|
||||||
|
|
||||||
|
merge_overlapping(selections, main_selection, overlaps);
|
||||||
|
}
|
||||||
|
|
||||||
void Editor::move_selections(CharCount offset, SelectMode mode)
|
void Editor::move_selections(CharCount offset, SelectMode mode)
|
||||||
{
|
{
|
||||||
kak_assert(mode == SelectMode::Replace or mode == SelectMode::Extend);
|
kak_assert(mode == SelectMode::Replace or mode == SelectMode::Extend);
|
||||||
|
@ -391,7 +391,7 @@ bool Editor::undo()
|
||||||
{
|
{
|
||||||
m_selections = std::move(listener.ranges());
|
m_selections = std::move(listener.ranges());
|
||||||
m_main_sel = m_selections.size() - 1;
|
m_main_sel = m_selections.size() - 1;
|
||||||
sort_and_merge_overlapping<true>(m_selections, m_main_sel);
|
merge_overlapping(m_selections, m_main_sel, touches);
|
||||||
}
|
}
|
||||||
check_invariant();
|
check_invariant();
|
||||||
return res;
|
return res;
|
||||||
|
@ -405,7 +405,7 @@ bool Editor::redo()
|
||||||
{
|
{
|
||||||
m_selections = std::move(listener.ranges());
|
m_selections = std::move(listener.ranges());
|
||||||
m_main_sel = m_selections.size() - 1;
|
m_main_sel = m_selections.size() - 1;
|
||||||
sort_and_merge_overlapping<true>(m_selections, m_main_sel);
|
merge_overlapping(m_selections, m_main_sel, touches);
|
||||||
}
|
}
|
||||||
check_invariant();
|
check_invariant();
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -45,6 +45,12 @@ inline bool overlaps(const Range& lhs, const Range& rhs)
|
||||||
(lhs.first() <= rhs.last() and lhs.last() >= rhs.last());
|
(lhs.first() <= rhs.last() and lhs.last() >= rhs.last());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool touches(const Range& lhs, const Range& rhs)
|
||||||
|
{
|
||||||
|
return lhs.begin() <= rhs.begin() ? lhs.end() >= rhs.begin()
|
||||||
|
: lhs.begin() <= rhs.end();
|
||||||
|
}
|
||||||
|
|
||||||
using CaptureList = std::vector<String>;
|
using CaptureList = std::vector<String>;
|
||||||
|
|
||||||
// A selection is a Range, associated with a CaptureList
|
// A selection is a Range, associated with a CaptureList
|
||||||
|
|
Loading…
Reference in New Issue
Block a user