summaryrefslogtreecommitdiff
path: root/src/selection.cc
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2021-09-29 21:28:30 +1000
committerMaxime Coste <mawww@kakoune.org>2021-09-30 20:12:58 +1000
commit5f8753caec8b9aba8e9793dab972d80a2f222d60 (patch)
tree4a4942df65c9ed6974455ef74eddd755c225a1d3 /src/selection.cc
parent05fb07fbc6c3a9fcccd69b03b01bf063f524868b (diff)
rework selection insert/replace using a for_each method
expose that method so that various commands can take advantage of it for performance or simplicity purposes.
Diffstat (limited to 'src/selection.cc')
-rw-r--r--src/selection.cc72
1 files changed, 36 insertions, 36 deletions
diff --git a/src/selection.cc b/src/selection.cc
index a552526d..27a40156 100644
--- a/src/selection.cc
+++ b/src/selection.cc
@@ -367,7 +367,7 @@ BufferCoord get_insert_pos(const Buffer& buffer, const Selection& sel,
case InsertMode::AppendAtLineEnd:
return {sel.max().line, buffer[sel.max().line].length() - 1};
case InsertMode::InsertAtNextLineBegin:
- return sel.max().line+1;
+ return std::min(buffer.line_count(), sel.max().line+1);
default:
kak_assert(false);
return {};
@@ -390,22 +390,15 @@ void SelectionList::insert(ConstArrayView<String> strings, InsertMode mode)
if (strings.empty())
return;
- insert([&](size_t index, BufferCoord) {
- return String::no_copy(strings[std::min(strings.size()-1, index)]);
- }, mode);
+ for_each([&](size_t index, Selection& sel) {
+ Kakoune::insert(*m_buffer, sel, strings[std::min(strings.size()-1, index)], mode);
+ });
}
-void SelectionList::insert(ContentFunc get_content, InsertMode mode)
+void SelectionList::for_each(ApplyFunc func)
{
update();
- Vector<BufferCoord> insert_pos;
- if (mode != InsertMode::Replace)
- {
- for (auto& sel : m_selections)
- insert_pos.push_back(get_insert_pos(*m_buffer, sel, mode));
- }
-
ForwardChangesTracker changes_tracker;
for (size_t index = 0; index < m_selections.size(); ++index)
{
@@ -413,42 +406,49 @@ void SelectionList::insert(ContentFunc get_content, InsertMode mode)
sel.anchor() = changes_tracker.get_new_coord_tolerant(sel.anchor());
sel.cursor() = changes_tracker.get_new_coord_tolerant(sel.cursor());
- kak_assert(m_buffer->is_valid(sel.anchor()) and
- m_buffer->is_valid(sel.cursor()));
+ kak_assert(m_buffer->is_valid(sel.anchor()) and m_buffer->is_valid(sel.cursor()));
- const auto pos = (mode == InsertMode::Replace) ?
- sel.min() : changes_tracker.get_new_coord(insert_pos[index]);
-
- String str = get_content(index, pos);
-
- if (mode == InsertMode::Replace)
- {
- auto range = replace(*m_buffer, sel, str);
- // we want min and max from *before* we do any change
- auto& min = sel.min();
- auto& max = sel.max();
- min = range.begin;
- max = range.end > range.begin ? m_buffer->char_prev(range.end) : range.begin;
- }
- else
- {
- auto range = m_buffer->insert(pos, str);
- sel.anchor() = m_buffer->clamp(update_insert(sel.anchor(), range.begin, range.end));
- sel.cursor() = m_buffer->clamp(update_insert(sel.cursor(), range.begin, range.end));
- }
+ func(index, sel);
changes_tracker.update(*m_buffer, m_timestamp);
}
// We might just have been deleting text if strings were empty,
// in which case we could have some selections pushed out of the buffer
- if (mode == InsertMode::Replace)
- fix_overflowing_selections(m_selections, *m_buffer);
+ fix_overflowing_selections(m_selections, *m_buffer);
check_invariant();
m_buffer->check_invariant();
}
+
+void replace(Buffer& buffer, Selection& sel, StringView content)
+{
+ // we want min and max from *before* we do any change
+ auto& min = sel.min();
+ auto& max = sel.max();
+ BufferRange range = buffer.replace(min, buffer.char_next(max), content);
+ min = range.begin;
+ max = range.end > range.begin ? buffer.char_prev(range.end) : range.begin;
+}
+
+void insert(Buffer& buffer, Selection& sel, StringView content, InsertMode mode)
+{
+ auto range = buffer.insert(get_insert_pos(buffer, sel, mode), content);
+ sel.anchor() = buffer.clamp(update_insert(sel.anchor(), range.begin, range.end));
+ sel.cursor() = buffer.clamp(update_insert(sel.cursor(), range.begin, range.end));
+}
+
+void SelectionList::replace(ConstArrayView<String> strings)
+{
+ if (strings.empty())
+ return;
+
+ for_each([&](size_t index, Selection& sel) {
+ Kakoune::replace(*m_buffer, sel, strings[std::min(strings.size()-1, index)]);
+ });
+}
+
void SelectionList::erase()
{
update();