kakoune/src/completion.hh
Maxime Coste 719512b308 Use a separate copy of the command completer for each completion
This make the completer lifetime tied to the Prompt mode and removes
the need for the Start flag. It also makes it possible to cleanup
on completer destruction.
2023-11-14 21:39:03 +11:00

93 lines
2.3 KiB
C++

#ifndef completion_hh_INCLUDED
#define completion_hh_INCLUDED
#include <functional>
#include <algorithm>
#include "units.hh"
#include "string.hh"
#include "vector.hh"
#include "ranked_match.hh"
namespace Kakoune
{
class Context;
using CandidateList = Vector<String, MemoryDomain::Completion>;
struct Completions
{
enum class Flags
{
None = 0,
Quoted = 0b1,
Menu = 0b10,
NoEmpty = 0b100
};
constexpr friend bool with_bit_ops(Meta::Type<Flags>) { return true; }
CandidateList candidates;
ByteCount start;
ByteCount end;
Flags flags = Flags::None;
Completions()
: start(0), end(0) {}
Completions(ByteCount start, ByteCount end)
: start(start), end(end) {}
Completions(ByteCount start, ByteCount end, CandidateList candidates, Flags flags = Flags::None)
: candidates(std::move(candidates)), start(start), end(end), flags{flags} {}
};
enum class CompletionFlags
{
None = 0,
Fast = 1 << 0,
};
constexpr bool with_bit_ops(Meta::Type<CompletionFlags>) { return true; }
inline Completions complete_nothing(const Context&, CompletionFlags,
StringView, ByteCount cursor_pos)
{
return {cursor_pos, cursor_pos};
}
Completions shell_complete(const Context& context, CompletionFlags,
StringView, ByteCount cursor_pos);
inline Completions offset_pos(Completions completion, ByteCount offset)
{
return {completion.start + offset, completion.end + offset,
std::move(completion.candidates), completion.flags};
}
template<typename Container>
CandidateList complete(StringView query, ByteCount cursor_pos,
const Container& container)
{
using std::begin;
static_assert(not std::is_same<decltype(*begin(container)), String>::value,
"complete require long lived strings, not temporaries");
query = query.substr(0, cursor_pos);
Vector<RankedMatch> matches;
for (const auto& str : container)
{
if (RankedMatch match{str, query})
matches.push_back(match);
}
std::sort(matches.begin(), matches.end());
CandidateList res;
for (auto& m : matches)
res.push_back(m.candidate().str());
return res;
}
}
#endif // completion_hh_INCLUDED