summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMaxime Coste <mawww@kakoune.org>2020-06-27 13:33:50 +1000
committerMaxime Coste <mawww@kakoune.org>2020-06-27 13:33:50 +1000
commitfc3e5ea419aa79c7adf38a9252586d867b3eb19b (patch)
tree95d82f8658ea2797fbf35aad6cb6ce846e479e7a
parent099b83d922aff0bd19ffc1a10a729afa07de91fb (diff)
Refactor how InsetCompletionHide hook parameter is computed
Keep track of inserted ranges instead of trying to re-derive them. Fixes #3556
-rw-r--r--src/array_view.hh2
-rw-r--r--src/buffer_utils.cc20
-rw-r--r--src/buffer_utils.hh2
-rw-r--r--src/insert_completer.cc45
-rw-r--r--src/insert_completer.hh1
-rw-r--r--src/range.hh2
6 files changed, 38 insertions, 34 deletions
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<typename Container,
typename = std::enable_if_t<sizeof(decltype(*std::declval<Container>().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<T>& 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 <unistd.h>
@@ -15,6 +16,25 @@
namespace Kakoune
{
+void replace(Buffer& buffer, ArrayView<BufferRange> ranges, ConstArrayView<String> 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<BufferRange> ranges, ConstArrayView<String> 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<Key>& keystrokes)
auto ref = buffer.string(m_completions.begin, m_completions.end);
ForwardChangesTracker changes_tracker;
- size_t timestamp = buffer.timestamp();
- Vector<BufferCoord> positions;
+ Vector<BufferRange> 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<InsertCompletion>(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<BufferRange> 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; }
};
}