diff --git a/src/array_view.hh b/src/array_view.hh index 52c89ac2..6a363656 100644 --- a/src/array_view.hh +++ b/src/array_view.hh @@ -32,7 +32,7 @@ public: template().data())) == sizeof(T)>> - constexpr ArrayView(const Container& c) + constexpr ArrayView(Container&& c) : m_pointer(c.data()), m_size(c.size()) {} constexpr ArrayView(const std::initializer_list& v) diff --git a/src/buffer_utils.cc b/src/buffer_utils.cc index d8daa944..206dc4b7 100644 --- a/src/buffer_utils.cc +++ b/src/buffer_utils.cc @@ -4,6 +4,7 @@ #include "event_manager.hh" #include "file.hh" #include "selection.hh" +#include "changes.hh" #include @@ -15,6 +16,25 @@ namespace Kakoune { +void replace(Buffer& buffer, ArrayView ranges, ConstArrayView strings) +{ + ForwardChangesTracker changes_tracker; + size_t timestamp = buffer.timestamp(); + for (size_t index = 0; index < ranges.size(); ++index) + { + auto& range = ranges[index]; + range.begin = changes_tracker.get_new_coord_tolerant(range.begin); + range.end = changes_tracker.get_new_coord_tolerant(range.end); + kak_assert(buffer.is_valid(range.begin) and buffer.is_valid(range.end)); + + range = buffer.replace(range.begin, range.end, strings.empty() ? StringView{} : strings[std::min(index, strings.size()-1)]); + kak_assert(buffer.is_valid(range.begin) and buffer.is_valid(range.end)); + changes_tracker.update(buffer, timestamp); + } + + buffer.check_invariant(); +} + ColumnCount get_column(const Buffer& buffer, ColumnCount tabstop, BufferCoord coord) { diff --git a/src/buffer_utils.hh b/src/buffer_utils.hh index 5af08e0e..dd5919a9 100644 --- a/src/buffer_utils.hh +++ b/src/buffer_utils.hh @@ -25,6 +25,8 @@ inline BufferRange replace(Buffer& buffer, const Selection& range, StringView co return buffer.replace(range.min(), buffer.char_next(range.max()), content); } +void replace(Buffer& buffer, ArrayView ranges, ConstArrayView strings); + inline CharCount char_length(const Buffer& buffer, const Selection& range) { return utf8::distance(buffer.iterator_at(range.min()), diff --git a/src/insert_completer.cc b/src/insert_completer.cc index f79d6c99..e3173517 100644 --- a/src/insert_completer.cc +++ b/src/insert_completer.cc @@ -413,31 +413,21 @@ void InsertCompleter::select(int index, bool relative, Vector& keystrokes) auto ref = buffer.string(m_completions.begin, m_completions.end); ForwardChangesTracker changes_tracker; - size_t timestamp = buffer.timestamp(); - Vector positions; + Vector ranges; for (auto& sel : selections) { - auto pos = buffer.iterator_at(changes_tracker.get_new_coord_tolerant(sel.cursor())); - if (pos.coord().column >= prefix_len and (pos + suffix_len) != buffer.end() and - std::equal(ref.begin(), ref.end(), pos - prefix_len)) - { - positions.push_back(buffer.erase((pos - prefix_len).coord(), - (pos + suffix_len).coord())); - changes_tracker.update(buffer, timestamp); - } - } - - changes_tracker = ForwardChangesTracker{}; - for (auto pos : positions) - { - buffer.insert(changes_tracker.get_new_coord_tolerant(pos), candidate.completion); - changes_tracker.update(buffer, timestamp); + auto pos = buffer.iterator_at(sel.cursor()); + if (pos.coord().column >= prefix_len and (pos + suffix_len) != buffer.end() and std::equal(ref.begin(), ref.end(), pos - prefix_len)) + ranges.push_back({(pos - prefix_len).coord(), (pos + suffix_len).coord()}); } + replace(buffer, ranges, candidate.completion); selections.update(); m_completions.end = cursor_pos; m_completions.begin = buffer.advance(cursor_pos, -candidate.completion.length()); m_completions.timestamp = buffer.timestamp(); + m_inserted_ranges = std::move(ranges); + if (m_context.has_client()) { m_context.client().menu_select(m_current_candidate); @@ -464,8 +454,8 @@ void InsertCompleter::update(bool allow_implicit) setup_ifn(); } -auto& get_first(InsertCompletion& completions) { return completions.begin; } -auto& get_last(InsertCompletion& completions) { return completions.end; } +auto& get_first(BufferRange& range) { return range.begin; } +auto& get_last(BufferRange& range) { return range.end; } void InsertCompleter::reset() { @@ -475,20 +465,9 @@ void InsertCompleter::reset() if (m_context.has_client() and m_current_candidate >= 0 and m_current_candidate < m_completions.candidates.size() - 1) { auto& buffer = m_context.buffer(); - update_ranges(buffer, m_completions.timestamp, - ArrayView(m_completions)); - auto ref = buffer.string(m_completions.begin, m_completions.end); - const auto& cursor_pos = m_context.selections().main().cursor(); - const auto prefix_len = buffer.distance(m_completions.begin, cursor_pos); - const auto suffix_len = std::max(0_byte, buffer.distance(cursor_pos, m_completions.end)); - hook_param = join(m_context.selections() | - transform([&](const auto& sel) { return buffer.iterator_at(sel.cursor()); }) | - filter([&](const auto& pos) { - return pos.coord().column >= prefix_len and (pos + suffix_len) != buffer.end() and - std::equal(ref.begin(), ref.end(), pos - prefix_len); - }) | - transform([&](const auto& pos) { - return selection_to_string(ColumnType::Byte, buffer, {(pos - prefix_len).coord(), buffer.char_prev((pos + suffix_len).coord())}); + update_ranges(buffer, m_completions.timestamp, m_inserted_ranges); + hook_param = join(m_inserted_ranges | filter([](auto&& r) { return not r.empty(); }) | transform([&](auto&& r) { + return selection_to_string(ColumnType::Byte, buffer, {r.begin, buffer.char_prev(r.end)}); }), ' '); } diff --git a/src/insert_completer.hh b/src/insert_completer.hh index 1270d732..b3c7480d 100644 --- a/src/insert_completer.hh +++ b/src/insert_completer.hh @@ -105,6 +105,7 @@ private: OptionManager& m_options; const FaceRegistry& m_faces; InsertCompletion m_completions; + Vector m_inserted_ranges; int m_current_candidate = -1; using CompleteFunc = InsertCompletion (const SelectionList& sels, diff --git a/src/range.hh b/src/range.hh index eb8be269..21443b51 100644 --- a/src/range.hh +++ b/src/range.hh @@ -24,6 +24,8 @@ struct Range { return hash_values(range.begin, range.end); } + + bool empty() const { return begin == end; } }; }