From fe2d0fab718078231c31f18607666a3deabb931c Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Mon, 20 Feb 2017 19:19:26 +0000 Subject: [PATCH] Fix performance of word completion with many different selections Fixes #1228 --- src/buffer.hh | 1 + src/buffer.inl.hh | 6 ++++++ src/insert_completer.cc | 24 +++++++++++------------- src/main.cc | 13 ++++++++++--- 4 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/buffer.hh b/src/buffer.hh index f449e863..81f68441 100644 --- a/src/buffer.hh +++ b/src/buffer.hh @@ -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; diff --git a/src/buffer.inl.hh b/src/buffer.inl.hh index 1880450d..d94ea42c 100644 --- a/src/buffer.inl.hh +++ b/src/buffer.inl.hh @@ -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::changes_since(size_t timestamp) const { if (timestamp < m_changes.size()) diff --git a/src/insert_completer.cc b/src/insert_completer.cc index f61a9c1d..f11c0bf7 100644 --- a/src/insert_completer.cc +++ b/src/insert_completer.cc @@ -90,25 +90,24 @@ InsertCompletion complete_word(const SelectionList& sels, const OptionManager& o return {}; BufferCoord word_begin; - String prefix; - IdMap sel_word_counts; + StringView prefix; + UnorderedMap 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(); const ColumnCount column = get_column(buffer, tabstop, cursor_pos); diff --git a/src/main.cc b/src/main.cc index 9d98468e..2e173282 100644 --- a/src/main.cc +++ b/src/main.cc @@ -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( + "completion_extra_word_char", + "Additional characters to be considered as words for insert completion", + ""_str); } static Client* local_client = nullptr;