summaryrefslogtreecommitdiff
path: root/src/buffer.cc
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2014-06-02 15:17:56 +0100
committerMaxime Coste <frrrwww@gmail.com>2014-06-02 15:17:56 +0100
commitc8354588c9af6a9d5064ec4e9665b1eea6c4eb77 (patch)
treee32f0f963068a614d9e73d616951150b670d3f16 /src/buffer.cc
parentd33c27acdf7ebf5c9be0ab1406ae4c7e66fb671e (diff)
Remove undo group optimizer
Diffstat (limited to 'src/buffer.cc')
-rw-r--r--src/buffer.cc188
1 files changed, 0 insertions, 188 deletions
diff --git a/src/buffer.cc b/src/buffer.cc
index 91f143c8..884ae270 100644
--- a/src/buffer.cc
+++ b/src/buffer.cc
@@ -181,200 +181,12 @@ struct Buffer::Modification
}
};
-class UndoGroupOptimizer
-{
- static constexpr auto Insert = Buffer::Modification::Type::Insert;
- static constexpr auto Erase = Buffer::Modification::Type::Erase;
-
- static ByteCoord advance(ByteCoord coord, const String& str)
- {
- for (auto c : str)
- {
- if (c == '\n')
- {
- ++coord.line;
- coord.column = 0;
- }
- else
- ++coord.column;
- }
- return coord;
- }
-
- static ByteCount count_byte_to(ByteCoord pos, ByteCoord endpos, const String& str)
- {
- ByteCount count = 0;
- for (auto it = str.begin(); it != str.end() and pos != endpos; ++it)
- {
- if (*it == '\n')
- {
- ++pos.line;
- pos.column = 0;
- }
- else
- ++pos.column;
- ++count;
- }
- kak_assert(pos == endpos);
- return count;
- }
-
- static const ByteCount overlaps(const String& lhs, const String& rhs)
- {
- if (lhs.empty() or rhs.empty())
- return -1;
-
- char c = rhs.front();
- ByteCount pos = 0;
- while ((pos = (int)lhs.find_first_of(c, (int)pos)) != -1)
- {
- ByteCount i = pos, j = 0;
- while (i != lhs.length() and j != rhs.length() and lhs[i] == rhs[j])
- ++i, ++j;
- if (i == lhs.length())
- break;
- ++pos;
- }
- return pos;
- }
-
- static bool merge_contiguous(Buffer::UndoGroup& undo_group)
- {
- bool progress = false;
- auto it = undo_group.begin();
- auto it_next = it+1;
- while (it_next != undo_group.end())
- {
- ByteCount pos;
- auto& coord = it->coord;
- auto& next_coord = it_next->coord;
-
- // reorders modification doing a kind of custom bubble sort
- // so we have a O(n²) worst case complexity of the undo group optimization
- if (next_coord < coord)
- {
- ByteCoord next_end = advance(next_coord, it_next->content);
- if (it_next->type == Insert)
- {
- if (coord.line == next_coord.line)
- coord.column += next_end.column - next_coord.column;
- coord.line += next_end.line - next_coord.line;
- }
- else if (it->type == Insert and next_end > coord)
- {
- ByteCount start = count_byte_to(next_coord, coord, it_next->content);
- ByteCount len = std::min(it->content.length(), it_next->content.length() - start);
- kak_assert(it_next->content.substr(start, len) == it->content.substr(0, len));
- it->coord = it_next->coord;
- it->content = it->content.substr(len);
- it_next->content = it_next->content.substr(0,start) + it_next->content.substr(start + len);
- }
- else if (it->type == Erase and next_end >= coord)
- {
- ByteCount start = count_byte_to(next_coord, coord, it_next->content);
- it_next->content = it_next->content.substr(0, start) + it->content + it_next->content.substr(start);
- it->coord = it_next->coord;
- it->content.clear();
- }
- else
- {
- if (next_end.line == coord.line)
- {
- coord.line = next_coord.line;
- coord.column = next_coord.column + coord.column - next_end.column;
- }
- else
- coord.line -= next_end.line - next_coord.line;
- }
- std::swap(*it, *it_next);
- progress = true;
- }
-
- kak_assert(coord <= next_coord);
- if (it->type == Erase and it_next->type == Erase and coord == next_coord)
- {
- it->content += it_next->content;
- it_next = undo_group.erase(it_next);
- progress = true;
- }
- else if (it->type == Insert and it_next->type == Insert and
- is_in_range(next_coord, coord, advance(coord, it->content)))
- {
- ByteCount prefix_len = count_byte_to(coord, next_coord, it->content);
- it->content = it->content.substr(0, prefix_len) + it_next->content
- + it->content.substr(prefix_len);
- it_next = undo_group.erase(it_next);
- progress = true;
- }
- else if (it->type == Insert and it_next->type == Erase and
- next_coord < advance(coord, it->content))
- {
- ByteCount insert_len = it->content.length();
- ByteCount erase_len = it_next->content.length();
- ByteCount prefix_len = count_byte_to(coord, next_coord, it->content);
-
- ByteCount suffix_len = insert_len - prefix_len;
- if (suffix_len >= erase_len)
- {
- it->content = it->content.substr(0, prefix_len) + it->content.substr(prefix_len + erase_len);
- it_next = undo_group.erase(it_next);
- }
- else
- {
- it->content = it->content.substr(0, prefix_len);
- it_next->content = it_next->content.substr(suffix_len);
- ++it, ++it_next;
- }
- progress = true;
- }
- else if (it->type == Erase and it_next->type == Insert and coord == next_coord and
- (pos = overlaps(it->content, it_next->content)) != -1)
- {
- ByteCount overlaps_len = it->content.length() - pos;
- it->content = it->content.substr(0, pos);
- it_next->coord = advance(it_next->coord, it_next->content.substr(0, overlaps_len));
- it_next->content = it_next->content.substr(overlaps_len);
- ++it, ++it_next;
- progress = true;
- }
- else
- ++it, ++it_next;
- }
- return progress;
- }
-
- static bool erase_empty(Buffer::UndoGroup& undo_group)
- {
- auto it = std::remove_if(begin(undo_group), end(undo_group),
- [](Buffer::Modification& m) { return m.content.empty(); });
- if (it != end(undo_group))
- {
- undo_group.erase(it, end(undo_group));
- return true;
- }
- return false;
- }
-public:
- static void optimize(Buffer::UndoGroup& undo_group)
- {
- while (undo_group.size() > 1)
- {
- bool progress = false;
- progress |= merge_contiguous(undo_group);
- progress |= erase_empty(undo_group);
- if (not progress)
- break;
- }
- }
-};
void Buffer::commit_undo_group()
{
if (m_flags & Flags::NoUndo)
return;
- UndoGroupOptimizer::optimize(m_current_undo_group);
-
if (m_current_undo_group.empty())
return;