diff options
| author | Maxime Coste <frrrwww@gmail.com> | 2015-05-21 22:58:50 +0100 |
|---|---|---|
| committer | Maxime Coste <frrrwww@gmail.com> | 2015-05-21 22:58:50 +0100 |
| commit | c38a7f3ca4d63c7da94c48afa47006315deee244 (patch) | |
| tree | 3203a792fbff34ad1760f6753fbb1adc5e4e9261 /src/buffer.cc | |
| parent | 43f76571517ac3b72bd7369e675f0500b9f31df5 (diff) | |
| parent | 41248c5728cf807939429a9f8a0c734e24c60c13 (diff) | |
Merge branch 'diff'
Diffstat (limited to 'src/buffer.cc')
| -rw-r--r-- | src/buffer.cc | 65 |
1 files changed, 47 insertions, 18 deletions
diff --git a/src/buffer.cc b/src/buffer.cc index c0167193..8b5f6ee5 100644 --- a/src/buffer.cc +++ b/src/buffer.cc @@ -9,6 +9,7 @@ #include "shared_string.hh" #include "utils.hh" #include "window.hh" +#include "diff.hh" #include <algorithm> @@ -159,36 +160,64 @@ struct Buffer::Modification void Buffer::reload(BufferLines lines, time_t fs_timestamp) { - m_changes.push_back({ Change::Erase, true, {0,0}, line_count() }); + if (lines.empty()) + lines.emplace_back(StringData::create("\n")); + + const bool record_undo = not (m_flags & Flags::NoUndo); commit_undo_group(); - if (not (m_flags & Flags::NoUndo)) + + if (not record_undo) { - for (auto line = line_count()-1; line >= 0; --line) - m_current_undo_group.emplace_back( - Modification::Erase, line, - SharedString{m_lines.get_storage(line)}); - } + m_changes.push_back({ Change::Erase, true, {0,0}, line_count() }); - if (lines.empty()) - lines.emplace_back(StringData::create("\n")); + static_cast<BufferLines&>(m_lines) = std::move(lines); - for (size_t l = 0; l < lines.size(); ++l) + m_changes.push_back({ Change::Insert, true, {0,0}, line_count() }); + } + else { - auto& line = lines[l]; - kak_assert(not (line->length == 0) and line->data()[line->length-1] == '\n'); - if (not (m_flags & Flags::NoUndo)) - m_current_undo_group.emplace_back( - Modification::Insert, LineCount{(int)l}, SharedString{line}); + auto diff = find_diff(m_lines.begin(), m_lines.size(), + lines.begin(), (int)lines.size(), + [](const StringDataPtr& lhs, const StringDataPtr& rhs) + { return lhs->hash == rhs->hash and lhs->strview() == rhs->strview(); }); + + auto it = m_lines.begin(); + for (auto& d : diff) + { + if (d.mode == Diff::Keep) + it += d.len; + else if (d.mode == Diff::Add) + { + const LineCount cur_line = (int)(it - m_lines.begin()); + + for (LineCount line = 0; line < d.len; ++line) + m_current_undo_group.emplace_back( + Modification::Insert, cur_line + line, + SharedString{lines[(int)(d.posB + line)]}); + + m_changes.push_back({ Change::Insert, it == m_lines.end(), cur_line, cur_line + d.len }); + it = m_lines.insert(it, &lines[d.posB], &lines[d.posB + d.len]) + d.len; + } + else if (d.mode == Diff::Remove) + { + const LineCount cur_line = (int)(it - m_lines.begin()); + + for (LineCount line = d.len-1; line >= 0; --line) + m_current_undo_group.emplace_back( + Modification::Erase, cur_line + line, + SharedString{m_lines.get_storage(cur_line + line)}); + + it = m_lines.erase(it, it + d.len); + m_changes.push_back({ Change::Erase, it == m_lines.end(), cur_line, cur_line + d.len }); + } + } } - static_cast<BufferLines&>(m_lines) = std::move(lines); commit_undo_group(); m_last_save_undo_index = m_history_cursor - m_history.begin(); m_fs_timestamp = fs_timestamp; - - m_changes.push_back({ Change::Insert, true, {0,0}, line_count() }); } void Buffer::commit_undo_group() |
