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; 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; CandidateList res;
while (res.size() < max_count and first != last) // Gather best max_count matches
{ for_n_best(matches, max_count, [](auto& lhs, auto& rhs) { return rhs < lhs; },
if (res.empty() or res.back() != first->candidate()) [&] (RankedMatch& m) {
res.push_back(first->candidate().str()); if (not res.empty() and res.back() == m.candidate())
std::pop_heap(first, last--, greater); return false;
} res.push_back(m.candidate().str());
return true;
});
return Completions{ 0_byte, pos_in_token, std::move(res) }; 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; constexpr size_t max_count = 100;
// Gather best max_count matches // 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; InsertCompletion::CandidateList candidates;
candidates.reserve(std::min(matches.size(), max_count)); candidates.reserve(std::min(matches.size(), max_count));
while (candidates.size() < max_count and first != last)
{ for_n_best(matches, max_count, [](auto& lhs, auto& rhs) { return rhs < lhs; },
if (candidates.empty() or candidates.back().completion != first->candidate()) [&](RankedMatchAndBuffer& m) {
{ if (not candidates.empty() and candidates.back().completion == m.candidate())
return false;
DisplayLine menu_entry; DisplayLine menu_entry;
if (other_buffers && first->buffer) if (other_buffers && m.buffer)
{ {
const auto pad_len = longest + 1 - first->candidate().char_length(); const auto pad_len = longest + 1 - m.candidate().char_length();
menu_entry.push_back(first->candidate().str()); menu_entry.push_back(m.candidate().str());
menu_entry.push_back(String{' ', pad_len}); 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 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)}); candidates.push_back({m.candidate().str(), "", std::move(menu_entry)});
} return true;
std::pop_heap(first, last--, greater); });
}
return { std::move(candidates), word_begin, cursor_pos, buffer.timestamp() }; 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); 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> template<typename Container>
auto gather() auto gather()
{ {