summary refs log tree commit diff
path: root/src/CompletionProxyModel.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/CompletionProxyModel.h')
-rw-r--r--src/CompletionProxyModel.h86
1 files changed, 50 insertions, 36 deletions
diff --git a/src/CompletionProxyModel.h b/src/CompletionProxyModel.h

index 5d3ae152..f19e4d93 100644 --- a/src/CompletionProxyModel.h +++ b/src/CompletionProxyModel.h
@@ -59,7 +59,7 @@ struct trie std::vector<Value> search(const QVector<Key> &keys, //< TODO(Nico): replace this with a span size_t result_count_limit, - size_t max_edit_distance = 2) const + size_t max_edit_distance_ = 2) const { std::vector<Value> ret; if (!result_count_limit) @@ -79,52 +79,66 @@ struct trie } }; - if (auto e = this->next.find(keys[0]); e != this->next.end()) { - append( - e->second.search(keys.mid(1), result_count_limit, max_edit_distance)); - } + auto limit = [&ret, result_count_limit] { + return std::min(result_count_limit, (result_count_limit - ret.size()) * 2); + }; - if (max_edit_distance && ret.size() < result_count_limit) { - max_edit_distance -= 1; + // Try first exact matches, then with maximum errors + for (size_t max_edit_distance = 0; + max_edit_distance <= max_edit_distance_ && ret.size() < result_count_limit; + max_edit_distance += 1) { + if (max_edit_distance && ret.size() < result_count_limit) { + max_edit_distance -= 1; - // swap chars case - if (keys.size() >= 2) { - auto t = this; - for (int i = 1; i >= 0; i--) { - if (auto e = t->next.find(keys[i]); e != t->next.end()) { - t = &e->second; - } else { - t = nullptr; - break; + // swap chars case + if (keys.size() >= 2) { + auto t = this; + for (int i = 1; i >= 0; i--) { + if (auto e = t->next.find(keys[i]); + e != t->next.end()) { + t = &e->second; + } else { + t = nullptr; + break; + } + } + + if (t) { + append(t->search( + keys.mid(2), limit(), max_edit_distance)); } } - if (t) { - append(t->search(keys.mid(2), - (result_count_limit - ret.size()) * 2, - max_edit_distance)); + // insert case + for (const auto &[k, t] : this->next) { + if (k == keys[0]) + continue; + if (ret.size() >= limit()) + break; + + // insert + append(t.search(keys, limit(), max_edit_distance)); } - } - // delete character case - append(this->search( - keys.mid(1), (result_count_limit - ret.size()) * 2, max_edit_distance)); + // delete character case + append(this->search(keys.mid(1), limit(), max_edit_distance)); - // substitute and insert cases - for (const auto &[k, t] : this->next) { - if (k == keys[0] || ret.size() >= result_count_limit) - break; + // substitute case + for (const auto &[k, t] : this->next) { + if (k == keys[0]) + continue; + if (ret.size() >= limit()) + break; - // substitute - append(t.search( - keys.mid(1), result_count_limit - ret.size(), max_edit_distance)); + // substitute + append(t.search(keys.mid(1), limit(), max_edit_distance)); + } - if (ret.size() >= result_count_limit) - break; + max_edit_distance += 1; + } - // insert - append(t.search( - keys, result_count_limit - ret.size(), max_edit_distance)); + if (auto e = this->next.find(keys[0]); e != this->next.end()) { + append(e->second.search(keys.mid(1), limit(), max_edit_distance)); } }