summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
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) };
}