From 38f146d84963e04cddb3e83b7f5f06c630bd5cd2 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Thu, 17 Mar 2016 12:36:49 +0000 Subject: [PATCH] Fix another bug in Buffer::replace implementation --- src/buffer.cc | 16 ++++++---------- test/unit/undo-after-replace-lines/cmd | 1 + test/unit/undo-after-replace-lines/in | 4 ++++ test/unit/undo-after-replace-lines/out | 1 + 4 files changed, 12 insertions(+), 10 deletions(-) create mode 100644 test/unit/undo-after-replace-lines/cmd create mode 100644 test/unit/undo-after-replace-lines/in create mode 100644 test/unit/undo-after-replace-lines/out diff --git a/src/buffer.cc b/src/buffer.cc index d96b727b..cee8870a 100644 --- a/src/buffer.cc +++ b/src/buffer.cc @@ -415,21 +415,14 @@ void Buffer::apply_modification(const Modification& modification) ByteCoord coord = modification.coord; kak_assert(is_valid(coord)); - // in modifications, end coords should be {line_count(), 0} - kak_assert((m_lines.empty() and coord == ByteCoord{0,0} ) or - coord != ByteCoord(line_count()-1, m_lines.back().length())); - switch (modification.type) { case Modification::Insert: - { do_insert(coord, content); break; - } case Modification::Erase: { - ByteCount count = content.length(); - ByteCoord end = advance(coord, count); + auto end = advance(coord, content.length()); kak_assert(string(coord, end) == content); do_erase(coord, end); break; @@ -453,7 +446,7 @@ ByteCoord Buffer::insert(ByteCoord pos, StringView content) // for undo and redo purpose it is better to use one past last line rather // than one past last char coord. - auto coord = is_end(pos) ? ByteCoord{line_count()} : pos; + auto coord = is_end(pos) ? 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()); @@ -489,7 +482,10 @@ ByteCoord Buffer::replace(ByteCoord begin, ByteCoord end, StringView content) else real_content = intern(content); - auto coord = is_end(pos) ? ByteCoord{line_count()} : pos; + 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()); diff --git a/test/unit/undo-after-replace-lines/cmd b/test/unit/undo-after-replace-lines/cmd new file mode 100644 index 00000000..4b0cc2ac --- /dev/null +++ b/test/unit/undo-after-replace-lines/cmd @@ -0,0 +1 @@ +ey%RuU diff --git a/test/unit/undo-after-replace-lines/in b/test/unit/undo-after-replace-lines/in new file mode 100644 index 00000000..9c2a7090 --- /dev/null +++ b/test/unit/undo-after-replace-lines/in @@ -0,0 +1,4 @@ +line 1 +line 2 +line 3 +line 4 diff --git a/test/unit/undo-after-replace-lines/out b/test/unit/undo-after-replace-lines/out new file mode 100644 index 00000000..78483296 --- /dev/null +++ b/test/unit/undo-after-replace-lines/out @@ -0,0 +1 @@ +linelinelineline