Extract a for_n_best algorithm from completion function

Provide the heap based n-best algorithm through a nice interface.
This commit is contained in:
Maxime Coste 2018-04-15 13:20:13 +10:00
parent c2759ac526
commit e207bd30d4
3 changed files with 39 additions and 30 deletions

View File

@ -993,17 +993,15 @@ void define_command(const ParametersParser& parser, Context& context, const Shel
}
constexpr size_t max_count = 100;
// Gather best max_count matches
auto greater = [](auto& lhs, auto& rhs) { return rhs < lhs; };
auto first = matches.begin(), last = matches.end();
std::make_heap(first, last, greater);
CandidateList res;
while (res.size() < max_count and first != last)
{
if (res.empty() or res.back() != first->candidate())
res.push_back(first->candidate().str());
std::pop_heap(first, last--, greater);
}
// Gather best max_count matches
for_n_best(matches, max_count, [](auto& lhs, auto& rhs) { return rhs < lhs; },
[&] (RankedMatch& m) {
if (not res.empty() and res.back() == m.candidate())
return false;
res.push_back(m.candidate().str());
return true;
});
return Completions{ 0_byte, pos_in_token, std::move(res) };
};

View File

@ -177,30 +177,27 @@ InsertCompletion complete_word(const SelectionList& sels,
constexpr size_t max_count = 100;
// Gather best max_count matches
auto greater = [](auto& lhs, auto& rhs) { return rhs < lhs; };
auto first = matches.begin(), last = matches.end();
std::make_heap(first, last, greater);
InsertCompletion::CandidateList candidates;
candidates.reserve(std::min(matches.size(), max_count));
while (candidates.size() < max_count and first != last)
{
if (candidates.empty() or candidates.back().completion != first->candidate())
{
for_n_best(matches, max_count, [](auto& lhs, auto& rhs) { return rhs < lhs; },
[&](RankedMatchAndBuffer& m) {
if (not candidates.empty() and candidates.back().completion == m.candidate())
return false;
DisplayLine menu_entry;
if (other_buffers && first->buffer)
if (other_buffers && m.buffer)
{
const auto pad_len = longest + 1 - first->candidate().char_length();
menu_entry.push_back(first->candidate().str());
const auto pad_len = longest + 1 - m.candidate().char_length();
menu_entry.push_back(m.candidate().str());
menu_entry.push_back(String{' ', pad_len});
menu_entry.push_back({ first->buffer->display_name(), faces["MenuInfo"] });
menu_entry.push_back({ m.buffer->display_name(), faces["MenuInfo"] });
}
else
menu_entry.push_back(first->candidate().str());
menu_entry.push_back(m.candidate().str());
candidates.push_back({first->candidate().str(), "", std::move(menu_entry)});
}
std::pop_heap(first, last--, greater);
}
candidates.push_back({m.candidate().str(), "", std::move(menu_entry)});
return true;
});
return { std::move(candidates), word_begin, cursor_pos, buffer.timestamp() };
}

View File

@ -364,6 +364,20 @@ Init accumulate(Range&& c, Init&& init, BinOp&& op)
return std::accumulate(begin(c), end(c), init, op);
}
template<typename Range, typename Compare, typename Func>
void for_n_best(Range&& c, size_t count, Compare&& compare, Func&& func)
{
using std::begin; using std::end;
auto b = begin(c), e = end(c);
std::make_heap(b, e, compare);
while (count > 0 and b != e)
{
if (func(*b))
--count;
std::pop_heap(b, e--, compare);
}
}
template<typename Container>
auto gather()
{