Fix performance of word completion with many different selections

Fixes #1228
This commit is contained in:
Maxime Coste 2017-02-20 19:19:26 +00:00
parent 5eef2b9105
commit fe2d0fab71
4 changed files with 28 additions and 16 deletions

View File

@ -143,6 +143,7 @@ public:
size_t current_history_id() const noexcept;
String string(BufferCoord begin, BufferCoord end) const;
StringView substr(BufferCoord begin, BufferCoord end) const;
const char& byte_at(BufferCoord c) const;
ByteCount distance(BufferCoord begin, BufferCoord end) const;

View File

@ -89,6 +89,12 @@ inline size_t Buffer::timestamp() const
return m_changes.size();
}
inline StringView Buffer::substr(BufferCoord begin, BufferCoord end) const
{
kak_assert(begin.line == end.line);
return m_lines[begin.line].substr(begin.column, end.column - begin.column);
}
inline ConstArrayView<Buffer::Change> Buffer::changes_since(size_t timestamp) const
{
if (timestamp < m_changes.size())

View File

@ -90,25 +90,24 @@ InsertCompletion complete_word(const SelectionList& sels, const OptionManager& o
return {};
BufferCoord word_begin;
String prefix;
IdMap<int> sel_word_counts;
StringView prefix;
UnorderedMap<StringView, int> sel_word_counts;
for (int i = 0; i < sels.size(); ++i)
{
Utf8It end{buffer.iterator_at(sels[i].cursor()), buffer};
Utf8It begin = end-1;
if (not skip_while_reverse(begin, buffer.begin(),
[&](Codepoint c) { return is_word_pred(c); }))
if (not skip_while_reverse(begin, buffer.begin(), is_word_pred))
++begin;
if (i == sels.main_index())
{
word_begin = begin.base().coord();
prefix = buffer.string(word_begin, end.base().coord());
prefix = buffer.substr(word_begin, end.base().coord());
}
skip_while(end, buffer.end(), [&](Codepoint c) { return is_word_pred(c); });
skip_while(end, buffer.end(), is_word_pred);
auto word = buffer.string(begin.base().coord(), end.base().coord());
StringView word = buffer.substr(begin.base().coord(), end.base().coord());
++sel_word_counts[word];
}
@ -137,8 +136,8 @@ InsertCompletion complete_word(const SelectionList& sels, const OptionManager& o
// Remove words that are being edited
for (auto& word_count : sel_word_counts)
{
if (get_word_db(buffer).get_word_occurences(word_count.key) <= word_count.value)
unordered_erase(matches, StringView{word_count.key});
if (get_word_db(buffer).get_word_occurences(word_count.first) <= word_count.second)
unordered_erase(matches, word_count.first);
}
if (other_buffers)
@ -156,7 +155,7 @@ InsertCompletion complete_word(const SelectionList& sels, const OptionManager& o
if (RankedMatch match{word, prefix})
matches.emplace_back(match, nullptr);
unordered_erase(matches, StringView{prefix});
unordered_erase(matches, prefix);
std::sort(matches.begin(), matches.end());
matches.erase(std::unique(matches.begin(), matches.end()), matches.end());
@ -206,7 +205,7 @@ InsertCompletion complete_filename(const SelectionList& sels,
if (begin == pos)
return {};
auto prefix = buffer.string(begin.coord(), pos.coord());
StringView prefix = buffer.substr(begin.coord(), pos.coord());
if (require_slash and not contains(prefix, '/'))
return {};
@ -273,8 +272,7 @@ InsertCompletion complete_option(const SelectionList& sels,
if (cursor_pos.line == coord.line and cursor_pos.column >= coord.column)
{
StringView query = buffer[coord.line].substr(
coord.column, cursor_pos.column - coord.column);
StringView query = buffer.substr(coord, cursor_pos);
const ColumnCount tabstop = options["tabstop"].get<int>();
const ColumnCount column = get_column(buffer, tabstop, cursor_pos);

View File

@ -237,6 +237,12 @@ static void check_timeout(const int& timeout)
throw runtime_error{"the minimum acceptable timeout is 50 milliseconds"};
}
static void check_extra_word_char(const String& extra_chars)
{
if (contains_that(extra_chars, is_blank))
throw runtime_error{"blanks are not accepted for extra completion characters"};
}
void register_options()
{
OptionsRegistry& reg = GlobalScope::instance().option_registry();
@ -303,9 +309,10 @@ void register_options()
"%val{bufname} %val{cursor_line}:%val{cursor_char_column} "_str);
reg.declare_option("debug", "various debug flags", DebugFlags::None);
reg.declare_option("readonly", "prevent buffers from being modified", false);
reg.declare_option("completion_extra_word_char",
"Additional characters to be considered as words for insert completion",
""_str);
reg.declare_option<String, check_extra_word_char>(
"completion_extra_word_char",
"Additional characters to be considered as words for insert completion",
""_str);
}
static Client* local_client = nullptr;