Refactor how InsetCompletionHide hook parameter is computed

Keep track of inserted ranges instead of trying to re-derive them.

Fixes #3556
This commit is contained in:
Maxime Coste 2020-06-27 13:33:50 +10:00
parent 099b83d922
commit fc3e5ea419
6 changed files with 38 additions and 34 deletions

View File

@ -32,7 +32,7 @@ public:
template<typename Container, template<typename Container,
typename = std::enable_if_t<sizeof(decltype(*std::declval<Container>().data())) == sizeof(T)>> 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()) {} : m_pointer(c.data()), m_size(c.size()) {}
constexpr ArrayView(const std::initializer_list<T>& v) constexpr ArrayView(const std::initializer_list<T>& v)

View File

@ -4,6 +4,7 @@
#include "event_manager.hh" #include "event_manager.hh"
#include "file.hh" #include "file.hh"
#include "selection.hh" #include "selection.hh"
#include "changes.hh"
#include <unistd.h> #include <unistd.h>
@ -15,6 +16,25 @@
namespace Kakoune 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 get_column(const Buffer& buffer,
ColumnCount tabstop, BufferCoord coord) ColumnCount tabstop, BufferCoord coord)
{ {

View File

@ -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); 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) inline CharCount char_length(const Buffer& buffer, const Selection& range)
{ {
return utf8::distance(buffer.iterator_at(range.min()), return utf8::distance(buffer.iterator_at(range.min()),

View File

@ -413,31 +413,21 @@ void InsertCompleter::select(int index, bool relative, Vector<Key>& keystrokes)
auto ref = buffer.string(m_completions.begin, m_completions.end); auto ref = buffer.string(m_completions.begin, m_completions.end);
ForwardChangesTracker changes_tracker; ForwardChangesTracker changes_tracker;
size_t timestamp = buffer.timestamp(); Vector<BufferRange> ranges;
Vector<BufferCoord> positions;
for (auto& sel : selections) for (auto& sel : selections)
{ {
auto pos = buffer.iterator_at(changes_tracker.get_new_coord_tolerant(sel.cursor())); auto pos = buffer.iterator_at(sel.cursor());
if (pos.coord().column >= prefix_len and (pos + suffix_len) != buffer.end() and if (pos.coord().column >= prefix_len and (pos + suffix_len) != buffer.end() and std::equal(ref.begin(), ref.end(), pos - prefix_len))
std::equal(ref.begin(), ref.end(), pos - prefix_len)) ranges.push_back({(pos - prefix_len).coord(), (pos + suffix_len).coord()});
{
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);
} }
replace(buffer, ranges, candidate.completion);
selections.update(); selections.update();
m_completions.end = cursor_pos; m_completions.end = cursor_pos;
m_completions.begin = buffer.advance(cursor_pos, -candidate.completion.length()); m_completions.begin = buffer.advance(cursor_pos, -candidate.completion.length());
m_completions.timestamp = buffer.timestamp(); m_completions.timestamp = buffer.timestamp();
m_inserted_ranges = std::move(ranges);
if (m_context.has_client()) if (m_context.has_client())
{ {
m_context.client().menu_select(m_current_candidate); m_context.client().menu_select(m_current_candidate);
@ -464,8 +454,8 @@ void InsertCompleter::update(bool allow_implicit)
setup_ifn(); setup_ifn();
} }
auto& get_first(InsertCompletion& completions) { return completions.begin; } auto& get_first(BufferRange& range) { return range.begin; }
auto& get_last(InsertCompletion& completions) { return completions.end; } auto& get_last(BufferRange& range) { return range.end; }
void InsertCompleter::reset() 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) if (m_context.has_client() and m_current_candidate >= 0 and m_current_candidate < m_completions.candidates.size() - 1)
{ {
auto& buffer = m_context.buffer(); auto& buffer = m_context.buffer();
update_ranges(buffer, m_completions.timestamp, update_ranges(buffer, m_completions.timestamp, m_inserted_ranges);
ArrayView<InsertCompletion>(m_completions)); hook_param = join(m_inserted_ranges | filter([](auto&& r) { return not r.empty(); }) | transform([&](auto&& r) {
auto ref = buffer.string(m_completions.begin, m_completions.end); return selection_to_string(ColumnType::Byte, buffer, {r.begin, buffer.char_prev(r.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())});
}), ' '); }), ' ');
} }

View File

@ -105,6 +105,7 @@ private:
OptionManager& m_options; OptionManager& m_options;
const FaceRegistry& m_faces; const FaceRegistry& m_faces;
InsertCompletion m_completions; InsertCompletion m_completions;
Vector<BufferRange> m_inserted_ranges;
int m_current_candidate = -1; int m_current_candidate = -1;
using CompleteFunc = InsertCompletion (const SelectionList& sels, using CompleteFunc = InsertCompletion (const SelectionList& sels,

View File

@ -24,6 +24,8 @@ struct Range
{ {
return hash_values(range.begin, range.end); return hash_values(range.begin, range.end);
} }
bool empty() const { return begin == end; }
}; };
} }