summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2014-05-14 20:56:27 +0100
committerMaxime Coste <frrrwww@gmail.com>2014-05-14 20:56:49 +0100
commit4e280977a2fcd7ca423b5909b435b896b256cdaf (patch)
treecaf34647ab26f749f5c63f5af71f34302bc5e261 /src
parentc3f4ef9ba2e8ca58acc6cf56e552341a5af62f5d (diff)
Iterate in reversed order on selections when modifing buffer
This way, update only needs to be called once everything is done as we always modify after the next selection to be used.
Diffstat (limited to 'src')
-rw-r--r--src/buffer_utils.hh14
-rw-r--r--src/input_handler.cc28
-rw-r--r--src/normal.cc42
-rw-r--r--src/selection.cc26
-rw-r--r--src/selection.hh6
-rw-r--r--src/selectors.hh2
6 files changed, 72 insertions, 46 deletions
diff --git a/src/buffer_utils.hh b/src/buffer_utils.hh
index bd617595..f47c2c26 100644
--- a/src/buffer_utils.hh
+++ b/src/buffer_utils.hh
@@ -24,20 +24,6 @@ inline CharCount char_length(const Buffer& buffer, const Selection& range)
utf8::next(buffer.iterator_at(range.max())));
}
-inline void avoid_eol(const Buffer& buffer, ByteCoord& coord)
-{
- const auto column = coord.column;
- const auto& line = buffer[coord.line];
- if (column != 0 and column == line.length() - 1)
- coord.column = line.byte_count_to(line.char_length() - 2);
-}
-
-inline void avoid_eol(const Buffer& buffer, Selection& sel)
-{
- avoid_eol(buffer, sel.anchor());
- avoid_eol(buffer, sel.cursor());
-}
-
CharCount get_column(const Buffer& buffer,
CharCount tabstop, ByteCoord coord);
diff --git a/src/input_handler.cc b/src/input_handler.cc
index 08cd7f44..459f6751 100644
--- a/src/input_handler.cc
+++ b/src/input_handler.cc
@@ -667,7 +667,7 @@ public:
}
else if (key == Key::Backspace)
{
- for (auto& sel : context().selections())
+ for (auto& sel : reversed(context().selections()))
{
if (sel.cursor() == ByteCoord{0,0})
continue;
@@ -677,7 +677,7 @@ public:
}
else if (key == Key::Erase)
{
- for (auto& sel : context().selections())
+ for (auto& sel : reversed(context().selections()))
{
auto pos = buffer.iterator_at(sel.cursor());
buffer.erase(pos, utf8::next(pos));
@@ -761,11 +761,12 @@ private:
auto& selections = context().selections();
for (size_t i = 0; i < selections.size(); ++i)
{
- size_t index = std::min(i, strings.size()-1);
- buffer.insert(buffer.iterator_at(selections[i].cursor()),
- strings[index]);
- selections.update();
+ size_t index = selections.size() - 1 - i;
+ const String& str = strings[std::min(index, strings.size()-1)];
+ buffer.insert(buffer.iterator_at(selections[index].cursor()),
+ str);
}
+ selections.update();
}
void insert(Codepoint key)
@@ -773,11 +774,9 @@ private:
auto str = codepoint_to_str(key);
auto& buffer = context().buffer();
auto& selections = context().selections();
- for (auto& sel : selections)
- {
+ for (auto& sel : reversed(selections))
buffer.insert(buffer.iterator_at(sel.cursor()), str);
- selections.update();
- }
+ selections.update();
context().hooks().run_hook("InsertChar", str, context());
}
@@ -786,7 +785,7 @@ private:
SelectionList& selections = context().selections();
Buffer& buffer = context().buffer();
- for (auto& sel : selections)
+ for (auto& sel : reversed(selections))
{
ByteCoord anchor, cursor;
switch (mode)
@@ -835,10 +834,10 @@ private:
if (buffer.is_end(cursor))
cursor = buffer.char_prev(cursor);
- selections.update();
sel.anchor() = anchor;
sel.cursor() = cursor;
}
+ selections.update();
if (mode == InsertMode::OpenLineBelow or mode == InsertMode::OpenLineAbove)
{
insert('\n');
@@ -859,12 +858,13 @@ private:
void on_disabled() override
{
- for (auto& sel : context().selections())
+ auto& selections = context().selections();
+ for (auto& sel : selections)
{
if (m_insert_mode == InsertMode::Append and sel.cursor().column > 0)
sel.cursor() = context().buffer().char_prev(sel.cursor());
- avoid_eol(context().buffer(), sel);
}
+ selections.avoid_eol();
}
enum class Mode { Default, Complete, InsertReg };
diff --git a/src/normal.cc b/src/normal.cc
index a8386b32..ff38c29d 100644
--- a/src/normal.cc
+++ b/src/normal.cc
@@ -23,13 +23,12 @@ namespace Kakoune
void erase(Buffer& buffer, SelectionList& selections)
{
- for (auto& sel : selections)
+ for (auto& sel : reversed(selections))
{
erase(buffer, sel);
- selections.update();
- avoid_eol(buffer, sel);
}
- selections.check_invariant();
+ selections.update();
+ selections.avoid_eol();
buffer.check_invariant();
}
@@ -66,20 +65,24 @@ BufferIterator prepare_insert(Buffer& buffer, const Selection& sel)
template<InsertMode mode>
void insert(Buffer& buffer, SelectionList& selections, const String& str)
{
- for (auto& sel : selections)
+ for (auto& sel : reversed(selections))
{
auto pos = prepare_insert<mode>(buffer, sel);
pos = buffer.insert(pos, str);
- selections.update();
- if (mode == InsertMode::Replace and pos != buffer.end())
+ if (mode == InsertMode::Replace)
{
+ if (pos == buffer.end())
+ --pos;
sel.anchor() = pos.coord();
sel.cursor() = str.empty() ?
pos.coord() : (pos + str.byte_count_to(str.char_length() - 1)).coord();
}
- avoid_eol(buffer, sel);
}
- selections.check_invariant();
+ if (mode == InsertMode::Replace)
+ selections.set_timestamp(buffer.timestamp());
+ else
+ selections.update();
+ selections.avoid_eol();
buffer.check_invariant();
}
@@ -90,20 +93,25 @@ void insert(Buffer& buffer, SelectionList& selections, memoryview<String> string
return;
for (size_t i = 0; i < selections.size(); ++i)
{
- auto& sel = selections[i];
+ size_t index = selections.size() - 1 - i;
+ auto& sel = selections[index];
auto pos = prepare_insert<mode>(buffer, sel);
- const String& str = strings[std::min(i, strings.size()-1)];
+ const String& str = strings[std::min(index, strings.size()-1)];
pos = buffer.insert(pos, str);
- selections.update();
- if (mode == InsertMode::Replace and pos != buffer.end())
+ if (mode == InsertMode::Replace)
{
+ if (pos == buffer.end())
+ --pos;
sel.anchor() = pos.coord();
sel.cursor() = (str.empty() ?
pos : pos + str.byte_count_to(str.char_length() - 1)).coord();
}
- avoid_eol(buffer, sel);
}
- selections.check_invariant();
+ if (mode == InsertMode::Replace)
+ selections.set_timestamp(buffer.timestamp());
+ else
+ selections.update();
+ selections.avoid_eol();
buffer.check_invariant();
}
@@ -1352,9 +1360,9 @@ void move(Context& context, int count)
: context.buffer().offset_coord(sel.cursor(), offset);
sel.anchor() = mode == SelectMode::Extend ? sel.anchor() : cursor;
- sel.cursor() = cursor;
- avoid_eol(context.buffer(), sel);
+ sel.cursor() = cursor;
}
+ selections.avoid_eol();
selections.sort_and_merge_overlapping();
}
diff --git a/src/selection.cc b/src/selection.cc
index 746253f9..1e8356ab 100644
--- a/src/selection.cc
+++ b/src/selection.cc
@@ -188,5 +188,31 @@ void SelectionList::sort_and_merge_overlapping()
std::stable_sort(begin(), end(), compare_selections);
merge_overlapping(overlaps);
}
+namespace
+{
+
+inline void _avoid_eol(const Buffer& buffer, ByteCoord& coord)
+{
+ const auto column = coord.column;
+ const auto& line = buffer[coord.line];
+ if (column != 0 and column == line.length() - 1)
+ coord.column = line.byte_count_to(line.char_length() - 2);
+}
+
+
+inline void _avoid_eol(const Buffer& buffer, Selection& sel)
+{
+ _avoid_eol(buffer, sel.anchor());
+ _avoid_eol(buffer, sel.cursor());
+}
+
+}
+
+void SelectionList::avoid_eol()
+{
+ update();
+ for (auto& sel : m_selections)
+ _avoid_eol(buffer(), sel);
+}
}
diff --git a/src/selection.hh b/src/selection.hh
index f8727b90..5f0ce459 100644
--- a/src/selection.hh
+++ b/src/selection.hh
@@ -73,6 +73,8 @@ struct SelectionList
void rotate_main(int count) { m_main = (m_main + count) % size(); }
+ void avoid_eol();
+
void push_back(const Selection& sel) { m_selections.push_back(sel); }
void push_back(Selection&& sel) { m_selections.push_back(std::move(sel)); }
@@ -92,6 +94,10 @@ struct SelectionList
iterator begin() { return m_selections.begin(); }
iterator end() { return m_selections.end(); }
+ using reverse_iterator = std::vector<Selection>::reverse_iterator;
+ reverse_iterator rbegin() { return m_selections.rbegin(); }
+ reverse_iterator rend() { return m_selections.rend(); }
+
using const_iterator = std::vector<Selection>::const_iterator;
const_iterator begin() const { return m_selections.begin(); }
const_iterator end() const { return m_selections.end(); }
diff --git a/src/selectors.hh b/src/selectors.hh
index d98b73bf..d5b0523d 100644
--- a/src/selectors.hh
+++ b/src/selectors.hh
@@ -13,8 +13,8 @@ inline void clear_selections(const Buffer& buffer, SelectionList& selections)
{
auto& sel = selections.main();
auto& pos = sel.cursor();
- avoid_eol(buffer, pos);
sel.anchor() = pos;
+ selections.avoid_eol();
selections = SelectionList{ buffer, std::move(sel) };
}