Rewrite PerArgumentCommandCompleter to use compile time dispatching
No need to store these vectors of std::functions around anymore.
This commit is contained in:
parent
8627c93e11
commit
d14c39ebdd
|
@ -672,23 +672,4 @@ Completions CommandManager::complete(const Context& context,
|
||||||
return Completions{};
|
return Completions{};
|
||||||
}
|
}
|
||||||
|
|
||||||
Completions PerArgumentCommandCompleter::operator()(const Context& context,
|
|
||||||
CompletionFlags flags,
|
|
||||||
CommandParameters params,
|
|
||||||
size_t token_to_complete,
|
|
||||||
ByteCount pos_in_token)
|
|
||||||
const
|
|
||||||
{
|
|
||||||
if (token_to_complete >= m_completers.size())
|
|
||||||
return Completions{};
|
|
||||||
|
|
||||||
// it is possible to try to complete a new argument
|
|
||||||
kak_assert(token_to_complete <= params.size());
|
|
||||||
|
|
||||||
const String& argument = token_to_complete < params.size() ?
|
|
||||||
params[token_to_complete] : String();
|
|
||||||
return m_completers[token_to_complete](context, flags, argument,
|
|
||||||
pos_in_token);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,27 +38,6 @@ enum class CommandFlags
|
||||||
|
|
||||||
template<> struct WithBitOps<CommandFlags> : std::true_type {};
|
template<> struct WithBitOps<CommandFlags> : std::true_type {};
|
||||||
|
|
||||||
class PerArgumentCommandCompleter
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using ArgumentCompleter = std::function<Completions (const Context&,
|
|
||||||
CompletionFlags flags,
|
|
||||||
const String&, ByteCount)>;
|
|
||||||
using ArgumentCompleterList = ConstArrayView<ArgumentCompleter>;
|
|
||||||
|
|
||||||
PerArgumentCommandCompleter(ArgumentCompleterList completers)
|
|
||||||
: m_completers(completers.begin(), completers.end()) {}
|
|
||||||
|
|
||||||
Completions operator()(const Context& context,
|
|
||||||
CompletionFlags flags,
|
|
||||||
CommandParameters params,
|
|
||||||
size_t token_to_complete,
|
|
||||||
ByteCount pos_in_token) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Vector<ArgumentCompleter, MemoryDomain::Commands> m_completers;
|
|
||||||
};
|
|
||||||
|
|
||||||
using CommandInfo = std::pair<String, String>;
|
using CommandInfo = std::pair<String, String>;
|
||||||
|
|
||||||
struct Token
|
struct Token
|
||||||
|
|
|
@ -62,15 +62,61 @@ Buffer* open_fifo(StringView name, StringView filename, bool scroll)
|
||||||
return create_fifo_buffer(name.str(), fd, scroll);
|
return create_fifo_buffer(name.str(), fd, scroll);
|
||||||
}
|
}
|
||||||
|
|
||||||
const PerArgumentCommandCompleter filename_completer({
|
template<typename... Completers> struct PerArgumentCommandCompleter;
|
||||||
|
|
||||||
|
template<> struct PerArgumentCommandCompleter<>
|
||||||
|
{
|
||||||
|
Completions operator()(const Context&, CompletionFlags, CommandParameters,
|
||||||
|
size_t, ByteCount) const { return {}; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Completer, typename... Rest>
|
||||||
|
struct PerArgumentCommandCompleter<Completer, Rest...> : PerArgumentCommandCompleter<Rest...>
|
||||||
|
{
|
||||||
|
template<typename C, typename... R,
|
||||||
|
typename = typename std::enable_if<not std::is_base_of<PerArgumentCommandCompleter<>,
|
||||||
|
typename std::remove_reference<C>::type>::value>::type>
|
||||||
|
PerArgumentCommandCompleter(C&& completer, R&&... rest)
|
||||||
|
: PerArgumentCommandCompleter<Rest...>(std::forward<R>(rest)...),
|
||||||
|
m_completer(std::forward<C>(completer)) {}
|
||||||
|
|
||||||
|
Completions operator()(const Context& context, CompletionFlags flags,
|
||||||
|
CommandParameters params, size_t token_to_complete,
|
||||||
|
ByteCount pos_in_token) const
|
||||||
|
{
|
||||||
|
if (token_to_complete == 0)
|
||||||
|
{
|
||||||
|
const String& arg = token_to_complete < params.size() ?
|
||||||
|
params[token_to_complete] : String();
|
||||||
|
return m_completer(context, flags, arg, pos_in_token);
|
||||||
|
}
|
||||||
|
return PerArgumentCommandCompleter<Rest...>::operator()(
|
||||||
|
context, flags, params, token_to_complete-1, pos_in_token);
|
||||||
|
}
|
||||||
|
|
||||||
|
Completer m_completer;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<typename... Completers>
|
||||||
|
PerArgumentCommandCompleter<
|
||||||
|
typename std::remove_cv<
|
||||||
|
typename std::remove_reference<Completers>::type
|
||||||
|
>::type...>
|
||||||
|
make_completer(Completers&&... completers)
|
||||||
|
{
|
||||||
|
return {std::forward<Completers>(completers)...};
|
||||||
|
}
|
||||||
|
|
||||||
|
auto filename_completer = make_completer(
|
||||||
[](const Context& context, CompletionFlags flags, const String& prefix, ByteCount cursor_pos)
|
[](const Context& context, CompletionFlags flags, const String& prefix, ByteCount cursor_pos)
|
||||||
{ return Completions{ 0_byte, cursor_pos,
|
{ return Completions{ 0_byte, cursor_pos,
|
||||||
complete_filename(prefix,
|
complete_filename(prefix,
|
||||||
context.options()["ignored_files"].get<Regex>(),
|
context.options()["ignored_files"].get<Regex>(),
|
||||||
cursor_pos) }; }
|
cursor_pos) }; });
|
||||||
});
|
|
||||||
|
|
||||||
static CandidateList complete_buffer_name(StringView query, ByteCount cursor_pos)
|
static Completions complete_buffer_name(const Context& context, CompletionFlags flags,
|
||||||
|
StringView prefix, ByteCount cursor_pos)
|
||||||
{
|
{
|
||||||
struct RankedMatchAndBuffer : RankedMatch
|
struct RankedMatchAndBuffer : RankedMatch
|
||||||
{
|
{
|
||||||
|
@ -83,7 +129,7 @@ static CandidateList complete_buffer_name(StringView query, ByteCount cursor_pos
|
||||||
const Buffer* buffer;
|
const Buffer* buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
query = query.substr(0, cursor_pos);
|
StringView query = prefix.substr(0, cursor_pos);
|
||||||
Vector<RankedMatchAndBuffer> filename_matches;
|
Vector<RankedMatchAndBuffer> filename_matches;
|
||||||
Vector<RankedMatchAndBuffer> matches;
|
Vector<RankedMatchAndBuffer> matches;
|
||||||
for (const auto& buffer : BufferManager::instance())
|
for (const auto& buffer : BufferManager::instance())
|
||||||
|
@ -109,13 +155,10 @@ static CandidateList complete_buffer_name(StringView query, ByteCount cursor_pos
|
||||||
for (auto& match : matches)
|
for (auto& match : matches)
|
||||||
res.push_back(match.buffer->display_name());
|
res.push_back(match.buffer->display_name());
|
||||||
|
|
||||||
return res;
|
return { 0, cursor_pos, res };
|
||||||
}
|
}
|
||||||
|
|
||||||
const PerArgumentCommandCompleter buffer_completer({
|
auto buffer_completer = make_completer(&complete_buffer_name);
|
||||||
[](const Context& context, CompletionFlags flags, const String& prefix, ByteCount cursor_pos)
|
|
||||||
{ return Completions{ 0_byte, cursor_pos, complete_buffer_name(prefix, cursor_pos) }; }
|
|
||||||
});
|
|
||||||
|
|
||||||
const ParameterDesc no_params{ {}, ParameterDesc::Flags::None, 0, 0 };
|
const ParameterDesc no_params{ {}, ParameterDesc::Flags::None, 0, 0 };
|
||||||
const ParameterDesc single_name_param{ {}, ParameterDesc::Flags::None, 1, 1 };
|
const ParameterDesc single_name_param{ {}, ParameterDesc::Flags::None, 1, 1 };
|
||||||
|
@ -843,9 +886,7 @@ void define_command(const ParametersParser& parser, Context& context, const Shel
|
||||||
CommandParameters params,
|
CommandParameters params,
|
||||||
size_t token_to_complete, ByteCount pos_in_token)
|
size_t token_to_complete, ByteCount pos_in_token)
|
||||||
{
|
{
|
||||||
const String& prefix = params[token_to_complete];
|
return complete_buffer_name(context, flags, params[token_to_complete], pos_in_token);
|
||||||
return Completions{ 0_byte, pos_in_token,
|
|
||||||
complete_buffer_name(prefix, pos_in_token) };
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else if (auto shell_cmd_opt = parser.get_switch("shell-completion"))
|
else if (auto shell_cmd_opt = parser.get_switch("shell-completion"))
|
||||||
|
@ -985,9 +1026,7 @@ const CommandDesc alias_cmd = {
|
||||||
ParameterDesc{{}, ParameterDesc::Flags::None, 3, 3},
|
ParameterDesc{{}, ParameterDesc::Flags::None, 3, 3},
|
||||||
CommandFlags::None,
|
CommandFlags::None,
|
||||||
CommandHelper{},
|
CommandHelper{},
|
||||||
PerArgumentCommandCompleter({
|
make_completer(&complete_scope, &complete_nothing, &complete_command_name),
|
||||||
complete_scope, complete_nothing, complete_command_name
|
|
||||||
}),
|
|
||||||
[](const ParametersParser& parser, Context& context, const ShellContext&)
|
[](const ParametersParser& parser, Context& context, const ShellContext&)
|
||||||
{
|
{
|
||||||
if (not CommandManager::instance().command_defined(parser[2]))
|
if (not CommandManager::instance().command_defined(parser[2]))
|
||||||
|
@ -1006,10 +1045,7 @@ const CommandDesc unalias_cmd = {
|
||||||
ParameterDesc{{}, ParameterDesc::Flags::None, 2, 3},
|
ParameterDesc{{}, ParameterDesc::Flags::None, 2, 3},
|
||||||
CommandFlags::None,
|
CommandFlags::None,
|
||||||
CommandHelper{},
|
CommandHelper{},
|
||||||
PerArgumentCommandCompleter({
|
make_completer(&complete_scope, &complete_nothing, &complete_command_name),
|
||||||
complete_scope, complete_nothing, complete_command_name
|
|
||||||
|
|
||||||
}),
|
|
||||||
[](const ParametersParser& parser, Context& context, const ShellContext&)
|
[](const ParametersParser& parser, Context& context, const ShellContext&)
|
||||||
{
|
{
|
||||||
AliasRegistry& aliases = get_scope(parser[0], context).aliases();
|
AliasRegistry& aliases = get_scope(parser[0], context).aliases();
|
||||||
|
@ -1057,12 +1093,12 @@ const CommandDesc debug_cmd = {
|
||||||
ParameterDesc{{}, ParameterDesc::Flags::SwitchesOnlyAtStart, 1},
|
ParameterDesc{{}, ParameterDesc::Flags::SwitchesOnlyAtStart, 1},
|
||||||
CommandFlags::None,
|
CommandFlags::None,
|
||||||
CommandHelper{},
|
CommandHelper{},
|
||||||
PerArgumentCommandCompleter({
|
make_completer(
|
||||||
[](const Context& context, CompletionFlags flags,
|
[](const Context& context, CompletionFlags flags,
|
||||||
const String& prefix, ByteCount cursor_pos) -> Completions {
|
const String& prefix, ByteCount cursor_pos) -> Completions {
|
||||||
auto c = {"info", "buffers", "options", "memory", "shared-strings"};
|
auto c = {"info", "buffers", "options", "memory", "shared-strings"};
|
||||||
return { 0_byte, cursor_pos, complete(prefix, cursor_pos, c) };
|
return { 0_byte, cursor_pos, complete(prefix, cursor_pos, c) };
|
||||||
} }),
|
}),
|
||||||
[](const ParametersParser& parser, Context& context, const ShellContext&)
|
[](const ParametersParser& parser, Context& context, const ShellContext&)
|
||||||
{
|
{
|
||||||
if (parser[0] == "info")
|
if (parser[0] == "info")
|
||||||
|
@ -1621,11 +1657,7 @@ const CommandDesc prompt_cmd = {
|
||||||
ClientManager::instance().complete_client_name(prefix, cursor_pos) };
|
ClientManager::instance().complete_client_name(prefix, cursor_pos) };
|
||||||
};
|
};
|
||||||
else if (parser.get_switch("buffer-completion"))
|
else if (parser.get_switch("buffer-completion"))
|
||||||
completer = [](const Context& context, CompletionFlags,
|
completer = complete_buffer_name;
|
||||||
StringView prefix, ByteCount cursor_pos) -> Completions {
|
|
||||||
return { 0_byte, cursor_pos,
|
|
||||||
complete_buffer_name(prefix, cursor_pos) };
|
|
||||||
};
|
|
||||||
else if (parser.get_switch("command-completion"))
|
else if (parser.get_switch("command-completion"))
|
||||||
completer = [](const Context& context, CompletionFlags flags,
|
completer = [](const Context& context, CompletionFlags flags,
|
||||||
StringView prefix, ByteCount cursor_pos) -> Completions {
|
StringView prefix, ByteCount cursor_pos) -> Completions {
|
||||||
|
@ -1838,7 +1870,7 @@ const CommandDesc face_cmd = {
|
||||||
ParameterDesc{{}, ParameterDesc::Flags::None, 2, 2},
|
ParameterDesc{{}, ParameterDesc::Flags::None, 2, 2},
|
||||||
CommandFlags::None,
|
CommandFlags::None,
|
||||||
CommandHelper{},
|
CommandHelper{},
|
||||||
PerArgumentCommandCompleter({ complete_face, complete_face }),
|
make_completer(&complete_face, &complete_face),
|
||||||
[](const ParametersParser& parser, Context& context, const ShellContext&)
|
[](const ParametersParser& parser, Context& context, const ShellContext&)
|
||||||
{
|
{
|
||||||
FaceRegistry::instance().register_alias(parser[0], parser[1], true);
|
FaceRegistry::instance().register_alias(parser[0], parser[1], true);
|
||||||
|
@ -1900,15 +1932,14 @@ const CommandDesc change_working_directory_cmd = {
|
||||||
single_optional_name_param,
|
single_optional_name_param,
|
||||||
CommandFlags::None,
|
CommandFlags::None,
|
||||||
CommandHelper{},
|
CommandHelper{},
|
||||||
PerArgumentCommandCompleter{{
|
make_completer(
|
||||||
[](const Context& context, CompletionFlags flags,
|
[](const Context& context, CompletionFlags flags,
|
||||||
const String& prefix, ByteCount cursor_pos) -> Completions {
|
const String& prefix, ByteCount cursor_pos) -> Completions {
|
||||||
return { 0_byte, cursor_pos,
|
return { 0_byte, cursor_pos,
|
||||||
complete_filename(prefix,
|
complete_filename(prefix,
|
||||||
context.options()["ignored_files"].get<Regex>(),
|
context.options()["ignored_files"].get<Regex>(),
|
||||||
cursor_pos, true) };
|
cursor_pos, true) };
|
||||||
}
|
}),
|
||||||
}},
|
|
||||||
[](const ParametersParser& parser, Context&, const ShellContext&)
|
[](const ParametersParser& parser, Context&, const ShellContext&)
|
||||||
{
|
{
|
||||||
StringView target = parser.positional_count() == 1 ? StringView{parser[0]} : "~";
|
StringView target = parser.positional_count() == 1 ? StringView{parser[0]} : "~";
|
||||||
|
|
Loading…
Reference in New Issue
Block a user