From 63a791d65118bf37606db36ee12287e890d528ea Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Sun, 11 Jun 2017 12:01:40 +0100 Subject: [PATCH] Fix the Buffer::end() madness Until now, buffer had multiple recognized end coordinates, either { line_count, 0 } or { line_count - 1, line[line_count - 1].length }. Now the only correct end coord is { line_count, 0 }, removing the need for various special cases. --- src/buffer.cc | 49 ++++++++++++---------------------------- src/buffer.hh | 5 ++-- src/buffer.inl.hh | 19 +++++++--------- src/line_modification.cc | 15 ++---------- src/selection.cc | 8 +++---- 5 files changed, 30 insertions(+), 66 deletions(-) diff --git a/src/buffer.cc b/src/buffer.cc index 1a92b8da..dc0dd93b 100644 --- a/src/buffer.cc +++ b/src/buffer.cc @@ -88,7 +88,7 @@ Buffer::Buffer(String name, Flags flags, StringView data, #endif static_cast(m_lines) = std::move(parsed_lines.lines); - m_changes.push_back({ Change::Insert, true, {0,0}, line_count() }); + m_changes.push_back({ Change::Insert, {0,0}, line_count() }); apply_options(options(), parsed_lines); @@ -241,11 +241,11 @@ void Buffer::reload(StringView data, timespec fs_timestamp) if (not record_undo) { - m_changes.push_back({ Change::Erase, true, {0,0}, line_count() }); + m_changes.push_back({ Change::Erase, {0,0}, line_count() }); static_cast(m_lines) = std::move(parsed_lines.lines); - m_changes.push_back({ Change::Insert, true, {0,0}, line_count() }); + m_changes.push_back({ Change::Insert, {0,0}, line_count() }); } else { @@ -268,7 +268,7 @@ void Buffer::reload(StringView data, timespec fs_timestamp) Modification::Insert, cur_line + line, parsed_lines.lines[(int)(d.posB + line)]); - m_changes.push_back({ Change::Insert, it == m_lines.end(), cur_line, cur_line + d.len }); + m_changes.push_back({ Change::Insert, cur_line, cur_line + d.len }); m_lines.insert(it, &parsed_lines.lines[d.posB], &parsed_lines.lines[d.posB + d.len]); it = m_lines.begin() + (int)(cur_line + d.len); } @@ -282,7 +282,7 @@ void Buffer::reload(StringView data, timespec fs_timestamp) 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 }); + m_changes.push_back({ Change::Erase, cur_line, cur_line + d.len }); } } } @@ -453,8 +453,6 @@ BufferCoord Buffer::do_insert(BufferCoord pos, StringView content) const bool at_end = is_end(pos); const bool append_lines = at_end and (m_lines.empty() or byte_at(back_coord()) == '\n'); - if (at_end) - pos = append_lines ? line_count() : end_coord(); const StringView prefix = append_lines ? StringView{} : m_lines[pos.line].substr(0, pos.column); @@ -490,7 +488,7 @@ BufferCoord Buffer::do_insert(BufferCoord pos, StringView content) const auto end = at_end ? line_count() : BufferCoord{ last_line, m_lines[last_line].length() - suffix.length() }; - m_changes.push_back({ Change::Insert, at_end, pos, end }); + m_changes.push_back({ Change::Insert, pos, end }); return pos; } @@ -502,7 +500,7 @@ BufferCoord Buffer::do_erase(BufferCoord begin, BufferCoord end) kak_assert(is_valid(begin)); kak_assert(is_valid(end)); StringView prefix = m_lines[begin.line].substr(0, begin.column); - StringView suffix = m_lines[end.line].substr(end.column); + StringView suffix = end.line == line_count() ? StringView{} : m_lines[end.line].substr(end.column); BufferCoord next; if (not prefix.empty() or not suffix.empty()) @@ -514,11 +512,11 @@ BufferCoord Buffer::do_erase(BufferCoord begin, BufferCoord end) } else { - m_lines.erase(m_lines.begin() + (int)begin.line, m_lines.begin() + (int)end.line + 1); - next = is_end(begin) ? end_coord() : BufferCoord{begin.line, 0}; + m_lines.erase(m_lines.begin() + (int)begin.line, m_lines.begin() + (int)end.line); + next = begin.line; } - m_changes.push_back({ Change::Erase, is_end(begin), begin, end }); + m_changes.push_back({ Change::Erase, begin, end }); return next; } @@ -584,24 +582,11 @@ BufferCoord Buffer::erase(BufferCoord begin, BufferCoord end) BufferCoord Buffer::replace(BufferCoord begin, BufferCoord end, StringView content) { - if (not (m_flags & Flags::NoUndo)) - m_current_undo_group.emplace_back(Modification::Erase, begin, - intern(string(begin, end))); - auto pos = do_erase(begin, end); + if (is_end(end) and not content.empty() and content.back() == '\n') + content = content.substr(0, content.length() - 1); - StringDataPtr real_content; - if (is_end(pos) and content.back() != '\n') - real_content = intern(content + "\n"); - else - real_content = intern(content); - - bool last_char_is_eol = not (m_lines.empty() or - m_lines.back().empty() or - m_lines.back().back() != '\n'); - auto coord = is_end(pos) and last_char_is_eol ? line_count() : pos; - if (not (m_flags & Flags::NoUndo)) - m_current_undo_group.emplace_back(Modification::Insert, coord, real_content); - return do_insert(pos, real_content->strview()); + auto pos = erase(begin, end); + return insert(pos, content); } bool Buffer::is_modified() const @@ -662,8 +647,6 @@ BufferCoord Buffer::char_next(BufferCoord coord) const coord.column = 0; } } - else if (coord.line == m_lines.size() - 1) - coord.column = m_lines.back().length(); else { ++coord.line; @@ -675,9 +658,7 @@ BufferCoord Buffer::char_next(BufferCoord coord) const BufferCoord Buffer::char_prev(BufferCoord coord) const { kak_assert(is_valid(coord)); - if (is_end(coord)) - return {(int)m_lines.size()-1, m_lines.back().length() - 1}; - else if (coord.column == 0) + if (coord.column == 0) { if (coord.line > 0) coord.column = m_lines[--coord.line].length() - 1; diff --git a/src/buffer.hh b/src/buffer.hh index d0fdffcb..d2679ba1 100644 --- a/src/buffer.hh +++ b/src/buffer.hh @@ -89,9 +89,9 @@ public: private: SafePtr m_buffer; - StringView m_line; BufferCoord m_coord; - LineCount m_last_line; + LineCount m_line_count; + StringView m_line; }; using BufferLines = Vector; @@ -205,7 +205,6 @@ public: { enum Type : char { Insert, Erase }; Type type; - bool at_end; BufferCoord begin; BufferCoord end; }; diff --git a/src/buffer.inl.hh b/src/buffer.inl.hh index 7d987c26..5904b9ff 100644 --- a/src/buffer.inl.hh +++ b/src/buffer.inl.hh @@ -17,8 +17,6 @@ inline BufferCoord Buffer::next(BufferCoord coord) const { if (coord.column < m_lines[coord.line].length() - 1) ++coord.column; - else if (coord.line == m_lines.size() - 1) - coord.column = m_lines.back().length(); else { ++coord.line; @@ -59,7 +57,6 @@ inline bool Buffer::is_valid(BufferCoord c) const return false; return (c.line < line_count() and c.column < m_lines[c.line].length()) or - (c.line == line_count() - 1 and c.column == m_lines.back().length()) or (c.line == line_count() and c.column == 0); } @@ -110,14 +107,13 @@ inline BufferCoord Buffer::back_coord() const inline BufferCoord Buffer::end_coord() const { - return m_lines.empty() ? - BufferCoord{0,0} : BufferCoord{ line_count() - 1, m_lines.back().length() }; + return line_count(); } inline BufferIterator::BufferIterator(const Buffer& buffer, BufferCoord coord) noexcept - : m_buffer(&buffer), m_coord(coord), - m_line((*m_buffer)[coord.line]), - m_last_line(buffer.line_count()-1) {} + : m_buffer{&buffer}, m_coord{coord}, + m_line_count{buffer.line_count()}, + m_line{coord.line < buffer.line_count() ? (*m_buffer)[coord.line] : StringView{}} {} inline bool BufferIterator::operator==(const BufferIterator& iterator) const noexcept { @@ -197,9 +193,10 @@ inline BufferIterator& BufferIterator::operator-=(ByteCount size) inline BufferIterator& BufferIterator::operator++() { - if (++m_coord.column == m_line.length() and m_coord.line != m_last_line) + if (++m_coord.column == m_line.length()) { - m_line = (*m_buffer)[++m_coord.line]; + m_line = (++m_coord.line < m_line_count) ? + (*m_buffer)[m_coord.line] : StringView{}; m_coord.column = 0; } return *this; @@ -207,7 +204,7 @@ inline BufferIterator& BufferIterator::operator++() inline BufferIterator& BufferIterator::operator--() { - if (m_coord.column == 0 and m_coord.line > 0) + if (m_coord.column == 0) { m_line = (*m_buffer)[--m_coord.line]; m_coord.column = m_line.length() - 1; diff --git a/src/line_modification.cc b/src/line_modification.cc index 3d6617dd..df2b9cbc 100644 --- a/src/line_modification.cc +++ b/src/line_modification.cc @@ -10,22 +10,11 @@ static LineModification make_line_modif(const Buffer::Change& change) { LineCount num_added = 0, num_removed = 0; if (change.type == Buffer::Change::Insert) - { num_added = change.end.line - change.begin.line; - // inserted a new line at buffer end but end coord is on same line - if (change.at_end and change.end.column != 0) - ++num_added; - } else - { num_removed = change.end.line - change.begin.line; - // removed last line, but end coord is on same line - if (change.at_end and change.end.column != 0) - ++num_removed; - } // modified a line - if (not change.at_end and - (change.begin.column != 0 or change.end.column != 0)) + if ((change.begin.column != 0 or change.end.column != 0)) { ++num_removed; ++num_added; @@ -116,7 +105,7 @@ UnitTest test_line_modifications{[]() { Buffer buffer("test", Buffer::Flags::None, "line 1\nline 2\n"); auto ts = buffer.timestamp(); - buffer.insert({1, 7}, "line 3"); + buffer.insert({2, 0}, "line 3"); auto modifs = compute_line_modifications(buffer, ts); kak_assert(modifs.size() == 1 and modifs[0] == LineModification{ 2, 2, 0, 1 }); diff --git a/src/selection.cc b/src/selection.cc index 05095dfa..4724e896 100644 --- a/src/selection.cc +++ b/src/selection.cc @@ -448,17 +448,15 @@ void SelectionList::erase() kak_assert(m_buffer->is_valid(sel.cursor())); auto pos = Kakoune::erase(*m_buffer, sel); - sel.anchor() = sel.cursor() = m_buffer->clamp(pos); + sel.anchor() = sel.cursor() = pos; changes_tracker.update(*m_buffer, m_timestamp); } BufferCoord back_coord = m_buffer->back_coord(); for (auto& sel : m_selections) { - if (sel.anchor() > back_coord) - sel.anchor() = back_coord; - if (sel.cursor() > back_coord) - sel.cursor() = back_coord; + auto pos = m_buffer->clamp(sel.cursor()); + sel.anchor() = sel.cursor() = std::min(pos, back_coord); } m_buffer->check_invariant();