Extract merge_overlapping as a free function template

This commit is contained in:
Maxime Coste 2014-06-01 15:57:12 +01:00
parent 5bcb55b6dd
commit 1b30c0f4fb
3 changed files with 35 additions and 39 deletions

View File

@ -1155,7 +1155,7 @@ void spaces_to_tabs(Context& context, int ts)
} }
} }
static boost::optional<SelectionList> compute_modified_ranges(Buffer& buffer, size_t timestamp) static std::vector<Selection> compute_modified_ranges(Buffer& buffer, size_t timestamp)
{ {
std::vector<Selection> ranges; std::vector<Selection> ranges;
for (auto& change : buffer.changes_since(timestamp)) for (auto& change : buffer.changes_since(timestamp))
@ -1183,29 +1183,25 @@ static boost::optional<SelectionList> compute_modified_ranges(Buffer& buffer, si
ranges.insert(it, Selection{pos, pos}); ranges.insert(it, Selection{pos, pos});
} }
} }
if (ranges.empty())
return {};
for (auto& sel : ranges) for (auto& sel : ranges)
{ {
sel.anchor() = buffer.clamp(sel.anchor()); sel.anchor() = buffer.clamp(sel.anchor());
sel.cursor() = buffer.clamp(sel.cursor()); sel.cursor() = buffer.clamp(sel.cursor());
} }
SelectionList result{buffer, std::move(ranges)};
auto touches = [&](const Selection& lhs, const Selection& rhs) { auto touches = [&](const Selection& lhs, const Selection& rhs) {
return lhs.min() <= rhs.min() ? buffer.char_next(lhs.max()) >= rhs.min() return lhs.min() <= rhs.min() ? buffer.char_next(lhs.max()) >= rhs.min()
: lhs.min() <= buffer.char_next(rhs.max()); : lhs.min() <= buffer.char_next(rhs.max());
}; };
result.merge_overlapping(touches); size_t main = 0;
merge_overlapping(ranges.begin(), ranges.end(), main, touches);
for (auto& sel : result) for (auto& sel : ranges)
{ {
if (sel.anchor() != sel.cursor()) if (sel.anchor() != sel.cursor())
sel.cursor() = buffer.char_prev(sel.cursor()); sel.cursor() = buffer.char_prev(sel.cursor());
} }
return result; return ranges;
} }
void undo(Context& context, int) void undo(Context& context, int)
@ -1216,8 +1212,8 @@ void undo(Context& context, int)
if (res) if (res)
{ {
auto ranges = compute_modified_ranges(buffer, timestamp); auto ranges = compute_modified_ranges(buffer, timestamp);
if (ranges) if (not ranges.empty())
context.selections() = std::move(*ranges); context.selections() = std::move(ranges);
} }
else if (not res) else if (not res)
context.print_status({ "nothing left to undo", get_color("Information") }); context.print_status({ "nothing left to undo", get_color("Information") });
@ -1232,8 +1228,8 @@ void redo(Context& context, int)
if (res) if (res)
{ {
auto ranges = compute_modified_ranges(buffer, timestamp); auto ranges = compute_modified_ranges(buffer, timestamp);
if (ranges) if (not ranges.empty())
context.selections() = std::move(*ranges); context.selections() = std::move(ranges);
} }
else if (not res) else if (not res)

View File

@ -166,7 +166,7 @@ void SelectionList::update()
sel.anchor() = m_buffer->clamp(sel.anchor()); sel.anchor() = m_buffer->clamp(sel.anchor());
sel.cursor() = m_buffer->clamp(sel.cursor()); sel.cursor() = m_buffer->clamp(sel.cursor());
} }
merge_overlapping(overlaps); m_selections.erase(merge_overlapping(begin(), end(), m_main, overlaps), end());
check_invariant(); check_invariant();
m_timestamp = m_buffer->timestamp(); m_timestamp = m_buffer->timestamp();
@ -208,7 +208,7 @@ void SelectionList::sort_and_merge_overlapping()
return begin < main_begin; return begin < main_begin;
}); });
std::stable_sort(begin(), end(), compare_selections); std::stable_sort(begin(), end(), compare_selections);
merge_overlapping(overlaps); m_selections.erase(merge_overlapping(begin(), end(), m_main, overlaps), end());
} }
namespace namespace
{ {

View File

@ -71,6 +71,30 @@ enum class InsertMode : unsigned
OpenLineAbove OpenLineAbove
}; };
template<typename Iterator, typename OverlapsFunc>
Iterator merge_overlapping(Iterator begin, Iterator end, size_t& main, OverlapsFunc overlaps)
{
kak_assert(std::is_sorted(begin, end, compare_selections));
size_t size = end - begin;
size_t i = 0;
for (size_t j = 1; j < size; ++j)
{
if (overlaps(begin[i], begin[j]))
{
begin[i].merge_with(begin[j]);
if (i < main)
--main;
}
else
{
++i;
if (i != j)
begin[i] = std::move(begin[j]);
}
}
return begin + i + 1;
}
struct SelectionList struct SelectionList
{ {
SelectionList(Buffer& buffer, Selection s); SelectionList(Buffer& buffer, Selection s);
@ -122,30 +146,6 @@ struct SelectionList
bool operator==(const SelectionList& other) const { return m_buffer == other.m_buffer and m_selections == other.m_selections; } bool operator==(const SelectionList& other) const { return m_buffer == other.m_buffer and m_selections == other.m_selections; }
bool operator!=(const SelectionList& other) const { return !((*this) == other); } bool operator!=(const SelectionList& other) const { return !((*this) == other); }
template<typename OverlapsFunc>
void merge_overlapping(OverlapsFunc overlaps)
{
kak_assert(std::is_sorted(begin(), end(), compare_selections));
size_t i = 0;
for (size_t j = 1; j < size(); ++j)
{
if (overlaps((*this)[i], (*this)[j]))
{
(*this)[i].merge_with((*this)[j]);
if (i < m_main)
--m_main;
}
else
{
++i;
if (i != j)
(*this)[i] = std::move((*this)[j]);
}
}
m_selections.erase(begin() + i + 1, end());
kak_assert(std::is_sorted(begin(), end(), compare_selections));
}
void sort_and_merge_overlapping(); void sort_and_merge_overlapping();
Buffer& buffer() const { return *m_buffer; } Buffer& buffer() const { return *m_buffer; }