summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2013-06-06 19:39:53 +0200
committerMaxime Coste <frrrwww@gmail.com>2013-06-06 19:44:08 +0200
commit2a74b0e9e23e927121908ef534393ffd1b80e8ca (patch)
tree5a7f99c72ff80ed959eb4264f58aaf451d39f7f0 /src
parentcf454ef904a93185c3e5318bc7b5c1d3d08fea39 (diff)
Buffer: insert and erase go back to taking iterators, and return iterators
Diffstat (limited to 'src')
-rw-r--r--src/buffer.cc40
-rw-r--r--src/buffer.hh10
-rw-r--r--src/commands.cc5
-rw-r--r--src/editor.cc87
-rw-r--r--src/filters.cc4
-rw-r--r--src/input_handler.cc5
-rw-r--r--src/normal.cc8
-rw-r--r--src/selection.hh5
-rw-r--r--src/unit_tests.cc34
9 files changed, 95 insertions, 103 deletions
diff --git a/src/buffer.cc b/src/buffer.cc
index 1b95fe9c..f46049de 100644
--- a/src/buffer.cc
+++ b/src/buffer.cc
@@ -412,12 +412,12 @@ void Buffer::check_invariant() const
#endif
}
-void Buffer::do_insert(const BufferCoord& pos, const String& content)
+BufferCoord Buffer::do_insert(const BufferCoord& pos, const String& content)
{
kak_assert(is_valid(pos));
if (content.empty())
- return;
+ return pos;
++m_timestamp;
ByteCount offset = this->offset(pos);
@@ -489,9 +489,10 @@ void Buffer::do_insert(const BufferCoord& pos, const String& content)
for (auto listener : m_change_listeners)
listener->on_insert(*this, begin, end);
+ return begin;
}
-void Buffer::do_erase(const BufferCoord& begin, const BufferCoord& end)
+BufferCoord Buffer::do_erase(const BufferCoord& begin, const BufferCoord& end)
{
kak_assert(is_valid(begin));
kak_assert(is_valid(end));
@@ -501,19 +502,25 @@ void Buffer::do_erase(const BufferCoord& begin, const BufferCoord& end)
String suffix = m_lines[end.line].content.substr(end.column);
Line new_line = { m_lines[begin.line].start, prefix + suffix };
+ BufferCoord next;
if (new_line.length() != 0)
{
m_lines.erase(m_lines.begin() + (int)begin.line, m_lines.begin() + (int)end.line);
m_lines[begin.line] = std::move(new_line);
+ next = begin;
}
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};
+ }
for (LineCount i = begin.line+1; i < line_count(); ++i)
m_lines[i].start -= length;
for (auto listener : m_change_listeners)
listener->on_erase(*this, begin, end);
+ return next;
}
void Buffer::apply_modification(const Modification& modification)
@@ -547,32 +554,33 @@ void Buffer::apply_modification(const Modification& modification)
}
}
-void Buffer::insert(BufferCoord pos, String content)
+BufferIterator Buffer::insert(const BufferIterator& pos, String content)
{
- kak_assert(is_valid(pos));
+ kak_assert(is_valid(pos.coord()));
if (content.empty())
- return;
+ return pos;
- if (is_end(pos) and content.back() != '\n')
+ if (pos == end() and content.back() != '\n')
content += '\n';
if (not (m_flags & Flags::NoUndo))
- m_current_undo_group.emplace_back(Modification::Insert, pos, content);
- do_insert(pos, content);
+ m_current_undo_group.emplace_back(Modification::Insert, pos.coord(), content);
+ return {*this, do_insert(pos.coord(), content)};
}
-void Buffer::erase(BufferCoord begin, BufferCoord end)
+BufferIterator Buffer::erase(BufferIterator begin, BufferIterator end)
{
- if (is_end(end) and (begin.column != 0 or begin == BufferCoord{0,0}))
- end = { line_count() - 1, m_lines.back().length() - 1};
+ // do not erase last \n except if we erase from the start of a line
+ if (end == this->end() and (begin.coord().column != 0 or begin == this->begin()))
+ --end;
if (begin == end)
- return;
+ return begin;
if (not (m_flags & Flags::NoUndo))
- m_current_undo_group.emplace_back(Modification::Erase, begin,
- string(begin, end));
- do_erase(begin, end);
+ m_current_undo_group.emplace_back(Modification::Erase, begin.coord(),
+ string(begin.coord(), end.coord()));
+ return {*this, do_erase(begin.coord(), end.coord())};
}
bool Buffer::is_modified() const
diff --git a/src/buffer.hh b/src/buffer.hh
index 26fa584a..61b9179e 100644
--- a/src/buffer.hh
+++ b/src/buffer.hh
@@ -100,8 +100,8 @@ public:
bool set_name(String name);
- void insert(BufferCoord pos, String content);
- void erase(BufferCoord begin, BufferCoord end);
+ BufferIterator insert(const BufferIterator& pos, String content);
+ BufferIterator erase(BufferIterator begin, BufferIterator end);
size_t timestamp() const { return m_timestamp; }
@@ -160,8 +160,6 @@ public:
void check_invariant() const;
private:
- friend class BufferIterator;
-
struct Line
{
ByteCount start;
@@ -179,8 +177,8 @@ private:
};
LineList m_lines;
- void do_insert(const BufferCoord& pos, const String& content);
- void do_erase(const BufferCoord& begin, const BufferCoord& end);
+ BufferCoord do_insert(const BufferCoord& pos, const String& content);
+ BufferCoord do_erase(const BufferCoord& begin, const BufferCoord& end);
String m_name;
Flags m_flags;
diff --git a/src/commands.cc b/src/commands.cc
index b46b1b63..4e62a65f 100644
--- a/src/commands.cc
+++ b/src/commands.cc
@@ -60,9 +60,8 @@ Buffer* open_fifo(const String& name , const String& filename, Context& context)
constexpr size_t buffer_size = 1024 * 16;
char data[buffer_size];
ssize_t count = read(watcher.fd(), data, buffer_size);
- buffer->insert(buffer->back_coord(),
- count > 0 ? String(data, data+count)
- : "*** kak: fifo closed ***\n");
+ buffer->insert(buffer->end()-1, count > 0 ? String(data, data+count)
+ : "*** kak: fifo closed ***\n");
ClientManager::instance().redraw_clients();
if (count <= 0)
{
diff --git a/src/editor.cc b/src/editor.cc
index 81abd0e4..5d2e4a81 100644
--- a/src/editor.cc
+++ b/src/editor.cc
@@ -44,43 +44,31 @@ void Editor::erase()
}
}
-static BufferCoord prepare_insert(Buffer& buffer, const Selection& sel,
- InsertMode mode)
+static BufferIterator prepare_insert(Buffer& buffer, const Selection& sel,
+ InsertMode mode)
{
switch (mode)
{
case InsertMode::Insert:
- return sel.min();
+ return buffer.iterator_at(sel.min());
case InsertMode::Replace:
- {
- BufferCoord pos = sel.min();
- Kakoune::erase(buffer, sel);
- return pos;
- }
+ return Kakoune::erase(buffer, sel);
case InsertMode::Append:
{
// special case for end of lines, append to current line instead
- auto& pos = std::max(sel.first(), sel.last());
- if (pos.column == buffer[pos.line].length() - 1)
- return pos;
- else
- return buffer.char_next(pos);
+ auto pos = buffer.iterator_at(sel.max());
+ return *pos == '\n' ? pos : utf8::next(pos);
}
case InsertMode::InsertAtLineBegin:
- return sel.min().line;
+ return buffer.iterator_at(sel.min().line);
case InsertMode::AppendAtLineEnd:
- return {sel.max().line, buffer[sel.max().line].length() - 1};
+ return buffer.iterator_at({sel.max().line, buffer[sel.max().line].length() - 1});
case InsertMode::InsertAtNextLineBegin:
- return sel.max().line+1;
+ return buffer.iterator_at(sel.max().line+1);
case InsertMode::OpenLineBelow:
+ return buffer.insert(buffer.iterator_at(sel.max().line + 1), "\n");
case InsertMode::OpenLineAbove:
- {
- auto line = mode == InsertMode::OpenLineAbove ?
- sel.min().line : sel.max().line + 1;
- buffer.insert(line, "\n");
- return line;
- }
-
+ return buffer.insert(buffer.iterator_at(sel.min().line), "\n");
}
kak_assert(false);
return {};
@@ -92,13 +80,13 @@ void Editor::insert(const String& str, InsertMode mode)
for (auto& sel : m_selections)
{
- BufferCoord pos = prepare_insert(*m_buffer, sel, mode);
- m_buffer->insert(pos, str);
- if (mode == InsertMode::Replace and not m_buffer->is_end(pos))
+ auto pos = prepare_insert(*m_buffer, sel, mode);
+ pos = m_buffer->insert(pos, str);
+ if (mode == InsertMode::Replace and pos != m_buffer->end())
{
- sel.first() = pos;
+ sel.first() = pos.coord();
sel.last() = str.empty() ?
- pos : m_buffer->advance(pos, str.byte_count_to(str.char_length() - 1));
+ pos.coord() : (pos + str.byte_count_to(str.char_length() - 1)).coord();
}
avoid_eol(*m_buffer, sel);
}
@@ -114,14 +102,14 @@ void Editor::insert(const memoryview<String>& strings, InsertMode mode)
for (size_t i = 0; i < selections().size(); ++i)
{
auto& sel = m_selections[i];
- BufferCoord pos = prepare_insert(*m_buffer, sel, mode);
+ auto pos = prepare_insert(*m_buffer, sel, mode);
const String& str = strings[std::min(i, strings.size()-1)];
- m_buffer->insert(pos, str);
- if (mode == InsertMode::Replace and not m_buffer->is_end(pos))
+ pos = m_buffer->insert(pos, str);
+ if (mode == InsertMode::Replace and pos != m_buffer->end())
{
- sel.first() = pos;
- sel.last() = str.empty() ?
- pos : m_buffer->advance(pos, str.byte_count_to(str.char_length() - 1));
+ sel.first() = pos.coord();
+ sel.last() = (str.empty() ?
+ pos : pos + str.byte_count_to(str.char_length() - 1)).coord();
}
avoid_eol(*m_buffer, sel);
}
@@ -462,27 +450,24 @@ IncrementalInserter::IncrementalInserter(Editor& editor, InsertMode mode)
BufferCoord first, last;
switch (mode)
{
- case InsertMode::Insert: first = sel.max(); last = sel.min(); break;
+ case InsertMode::Insert:
+ first = sel.max();
+ last = sel.min();
+ break;
case InsertMode::Replace:
- {
- Kakoune::erase(buffer, sel);
- first = last = sel.min();
+ first = last = Kakoune::erase(buffer, sel).coord();
break;
- }
case InsertMode::Append:
- {
first = sel.min();
- last = sel.max();
+ last = sel.max();
// special case for end of lines, append to current line instead
if (last.column != buffer[last.line].length() - 1)
last = buffer.char_next(last);
break;
- }
case InsertMode::OpenLineBelow:
case InsertMode::AppendAtLineEnd:
- first = BufferCoord{sel.max().line, buffer[sel.max().line].length() - 1};
- last = first;
+ first = last = BufferCoord{sel.max().line, buffer[sel.max().line].length() - 1};
break;
case InsertMode::OpenLineAbove:
@@ -540,30 +525,32 @@ IncrementalInserter::~IncrementalInserter()
void IncrementalInserter::insert(String content)
{
- Buffer& buffer = m_editor.buffer();
+ auto& buffer = m_editor.buffer();
for (auto& sel : m_editor.m_selections)
{
m_editor.filters()(buffer, sel, content);
- buffer.insert(sel.last(), content);
+ buffer.insert(buffer.iterator_at(sel.last()), content);
}
}
void IncrementalInserter::insert(const memoryview<String>& strings)
{
+ auto& buffer = m_editor.buffer();
for (size_t i = 0; i < m_editor.m_selections.size(); ++i)
{
size_t index = std::min(i, strings.size()-1);
- m_editor.buffer().insert(m_editor.m_selections[i].last(),
- strings[index]);
+ buffer.insert(buffer.iterator_at(m_editor.m_selections[i].last()),
+ strings[index]);
}
}
void IncrementalInserter::erase()
{
+ auto& buffer = m_editor.buffer();
for (auto& sel : m_editor.m_selections)
{
- BufferCoord pos = sel.last();
- m_editor.buffer().erase(m_editor.buffer().char_prev(pos), pos);
+ auto pos = buffer.iterator_at(sel.last());
+ buffer.erase(pos-1, pos);
}
}
diff --git a/src/filters.cc b/src/filters.cc
index 61d98bca..02be6767 100644
--- a/src/filters.cc
+++ b/src/filters.cc
@@ -31,7 +31,7 @@ void cleanup_whitespaces(Buffer& buffer, Selection& selection, String& content)
--whitespace_start;
++whitespace_start;
if (whitespace_start != position)
- buffer.erase(whitespace_start.coord(), position.coord());
+ buffer.erase(whitespace_start, position);
}
}
@@ -81,10 +81,10 @@ struct RegexFilter
{
String suffix(it+1, content.end());
content = String(content.begin(), it-1);
+ buffer.insert(position, suffix);
auto& first = selection.first();
auto& last = selection.last();
- buffer.insert(last, suffix);
if (first == last)
first = buffer.advance(first, -suffix.length());
last = buffer.advance(last, -suffix.length());
diff --git a/src/input_handler.cc b/src/input_handler.cc
index 6dc74390..283b86ea 100644
--- a/src/input_handler.cc
+++ b/src/input_handler.cc
@@ -613,9 +613,8 @@ public:
if (offset >= beg_offset and offset + end_offset < buffer_len and
std::equal(pos - beg_offset, pos, begin))
{
- auto beg = buffer.advance(sel.last(), -beg_offset);
- buffer.erase(beg, buffer.advance(sel.last(), end_offset));
- buffer.insert(beg, candidate);
+ pos = buffer.erase(pos - beg_offset, pos + end_offset);
+ buffer.insert(pos, candidate);
}
}
diff --git a/src/normal.cc b/src/normal.cc
index a0fba585..fb5306e7 100644
--- a/src/normal.cc
+++ b/src/normal.cc
@@ -474,9 +474,9 @@ void join_select_spaces(Context& context)
SelectionList res = select_all_matches(buffer, sel, Regex{"(\n\\h*)+"});
// remove last end of line if selected
kak_assert(std::is_sorted(res.begin(), res.end(),
- [](const Selection& lhs, const Selection& rhs)
- { return lhs.min() < rhs.min(); }));
- if (not res.empty() and buffer.is_end(buffer.char_next(res.back().max())))
+ [](const Selection& lhs, const Selection& rhs)
+ { return lhs.min() < rhs.min(); }));
+ if (not res.empty() and res.back().max() == buffer.back_coord())
res.pop_back();
return res;
});
@@ -713,7 +713,7 @@ void align(Context& context)
for (auto& sel : selections)
{
CharCount padding = max_col - get_column(sel.last());
- buffer.insert(sel.last(), String{ ' ', padding });
+ buffer.insert(buffer.iterator_at(sel.last()), String{ ' ', padding });
}
}
diff --git a/src/selection.hh b/src/selection.hh
index c7e5e2c3..fb5f20dd 100644
--- a/src/selection.hh
+++ b/src/selection.hh
@@ -45,9 +45,10 @@ inline String content(const Buffer& buffer, const Range& range)
return buffer.string(range.min(), buffer.char_next(range.max()));
}
-inline void erase(Buffer& buffer, const Range& range)
+inline BufferIterator erase(Buffer& buffer, const Range& range)
{
- return buffer.erase(range.min(), buffer.char_next(range.max()));
+ return buffer.erase(buffer.iterator_at(range.min()),
+ utf8::next(buffer.iterator_at(range.max())));
}
using CaptureList = std::vector<String>;
diff --git a/src/unit_tests.cc b/src/unit_tests.cc
index 52f11ea1..00f54eb3 100644
--- a/src/unit_tests.cc
+++ b/src/unit_tests.cc
@@ -13,16 +13,16 @@ void test_buffer()
Buffer buffer("test", Buffer::Flags::None, { "allo ?\n", "mais que fais la police\n", " hein ?\n", " youpi\n" });
kak_assert(buffer.line_count() == 4);
- BufferCoord pos = {0,0};
- kak_assert(buffer.byte_at(pos) == 'a');
- pos = buffer.advance(pos, 6);
- kak_assert(pos == BufferCoord{0 COMMA 6});
- pos = buffer.next(pos);
- kak_assert(pos == BufferCoord{1 COMMA 0});
- pos = buffer.prev(pos);
- kak_assert(pos == BufferCoord{0 COMMA 6});
- pos = buffer.advance(pos, 1);
- kak_assert(pos == BufferCoord{1 COMMA 0});
+ BufferIterator pos = buffer.begin();
+ kak_assert(*pos == 'a');
+ pos += 6;
+ kak_assert(pos.coord() == BufferCoord{0 COMMA 6});
+ ++pos;
+ kak_assert(pos.coord() == BufferCoord{1 COMMA 0});
+ --pos;
+ kak_assert(pos.coord() == BufferCoord{0 COMMA 6});
+ pos += 1;
+ kak_assert(pos.coord() == BufferCoord{1 COMMA 0});
buffer.insert(pos, "tchou kanaky\n");
kak_assert(buffer.line_count() == 5);
@@ -30,17 +30,17 @@ void test_buffer()
kak_assert(str == "youpi");
// check insert at end behaviour: auto add end of line if necessary
- pos = buffer.back_coord();
+ pos = buffer.end()-1;
buffer.insert(pos, "tchou");
- kak_assert(buffer.string(pos, buffer.end_coord()) == "tchou\n");
+ kak_assert(buffer.string(pos.coord(), buffer.end_coord()) == "tchou\n");
- pos = buffer.back_coord();
- buffer.insert(buffer.end_coord(), "kanaky\n");
- kak_assert(buffer.string(buffer.next(pos), buffer.end_coord()) == "kanaky\n");
+ pos = buffer.end()-1;
+ buffer.insert(buffer.end(), "kanaky\n");
+ kak_assert(buffer.string((pos+1).coord(), buffer.end_coord()) == "kanaky\n");
buffer.commit_undo_group();
- buffer.erase(buffer.next(pos), buffer.end_coord());
- buffer.insert(buffer.end_coord(), "mutch\n");
+ buffer.erase(pos+1, buffer.end());
+ buffer.insert(buffer.end(), "mutch\n");
buffer.commit_undo_group();
buffer.undo();
kak_assert(buffer.string(buffer.advance(buffer.end_coord(), -7), buffer.end_coord()) == "kanaky\n");