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.
This commit is contained in:
Maxime Coste 2017-06-11 12:01:40 +01:00
parent b4647a16dd
commit 63a791d651
5 changed files with 30 additions and 66 deletions

View File

@ -88,7 +88,7 @@ Buffer::Buffer(String name, Flags flags, StringView data,
#endif
static_cast<BufferLines&>(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<BufferLines&>(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;

View File

@ -89,9 +89,9 @@ public:
private:
SafePtr<const Buffer> m_buffer;
StringView m_line;
BufferCoord m_coord;
LineCount m_last_line;
LineCount m_line_count;
StringView m_line;
};
using BufferLines = Vector<StringDataPtr, MemoryDomain::BufferContent>;
@ -205,7 +205,6 @@ public:
{
enum Type : char { Insert, Erase };
Type type;
bool at_end;
BufferCoord begin;
BufferCoord end;
};

View File

@ -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;

View File

@ -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 });

View File

@ -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();