Add support for command completion on commands, use it for :new

That means commands can be completed using other commands and their
completers. Yes that does makes sense.

Closes #296
This commit is contained in:
Maxime Coste 2015-06-26 13:52:01 +01:00
parent b579f90bae
commit 5b554ff474
5 changed files with 55 additions and 2 deletions

View File

@ -23,6 +23,7 @@ decl str termcmd %sh{
def -docstring 'create a new kak client for current session' \ def -docstring 'create a new kak client for current session' \
-shell-params \ -shell-params \
-command-completion \
new %{ %sh{ new %{ %sh{
if [ -z "${kak_opt_termcmd}" ]; then if [ -z "${kak_opt_termcmd}" ]; then
echo "echo -color Error 'termcmd option is not set'" echo "echo -color Error 'termcmd option is not set'"

View File

@ -506,7 +506,7 @@ Completions CommandManager::complete(const Context& context,
} }
} }
// command name completion // command name completion
if (tokens.empty() or if (tokens.empty() or
(tok_idx == cmd_idx and (tok_idx == tokens.size() or (tok_idx == cmd_idx and (tok_idx == tokens.size() or
tokens[tok_idx].type() == Token::Type::Raw))) tokens[tok_idx].type() == Token::Type::Raw)))
@ -589,6 +589,40 @@ Completions CommandManager::complete(const Context& context,
return Completions{}; return Completions{};
} }
Completions CommandManager::complete(const Context& context,
CompletionFlags flags,
CommandParameters params,
size_t token_to_complete,
ByteCount pos_in_token)
{
StringView prefix = params[token_to_complete].substr(0, pos_in_token);
if (token_to_complete == 0)
{
CandidateList candidates;
for (auto& command : m_commands)
{
if (command.second.flags & CommandFlags::Hidden)
continue;
if (prefix_match(command.first, prefix))
candidates.push_back(command.first);
}
std::sort(candidates.begin(), candidates.end());
return {0, pos_in_token, std::move(candidates)};
}
else
{
const String& command_name = params[0];
auto command_it = find_command(context, command_name);
if (command_it != m_commands.end() and command_it->second.completer)
return command_it->second.completer(
context, flags, params.subrange(1, params.size()-1),
token_to_complete-1, pos_in_token);
}
return Completions{};
}
Completions PerArgumentCommandCompleter::operator()(const Context& context, Completions PerArgumentCommandCompleter::operator()(const Context& context,
CompletionFlags flags, CompletionFlags flags,
CommandParameters params, CommandParameters params,

View File

@ -67,6 +67,10 @@ public:
Completions complete(const Context& context, CompletionFlags flags, Completions complete(const Context& context, CompletionFlags flags,
StringView command_line, ByteCount cursor_pos); StringView command_line, ByteCount cursor_pos);
Completions complete(const Context& context, CompletionFlags flags,
CommandParameters params,
size_t token_to_complete, ByteCount pos_in_token);
CommandInfo command_info(const Context& context, CommandInfo command_info(const Context& context,
StringView command_line) const; StringView command_line) const;

View File

@ -798,6 +798,16 @@ void define_command(const ParametersParser& parser, Context& context)
return Completions{ 0_byte, pos_in_token, split(output, '\n', 0) }; return Completions{ 0_byte, pos_in_token, split(output, '\n', 0) };
}; };
} }
else if (parser.get_switch("command-completion"))
{
completer = [](const Context& context, CompletionFlags flags,
CommandParameters params,
size_t token_to_complete, ByteCount pos_in_token)
{
return CommandManager::instance().complete(
context, flags, params, token_to_complete, pos_in_token);
};
}
auto docstring = parser.get_switch("docstring").value_or(StringView{}); auto docstring = parser.get_switch("docstring").value_or(StringView{});
@ -816,6 +826,7 @@ const CommandDesc define_command_cmd = {
{ "file-completion", { false, "complete parameters using filename completion" } }, { "file-completion", { false, "complete parameters using filename completion" } },
{ "client-completion", { false, "complete parameters using client name completion" } }, { "client-completion", { false, "complete parameters using client name completion" } },
{ "buffer-completion", { false, "complete parameters using buffer name completion" } }, { "buffer-completion", { false, "complete parameters using buffer name completion" } },
{ "command-completion", { false, "complete parameters using kakoune command completion" } },
{ "shell-completion", { true, "complete the parameters using the given shell-script" } } }, { "shell-completion", { true, "complete the parameters using the given shell-script" } } },
ParameterDesc::Flags::None, ParameterDesc::Flags::None,
2, 2 2, 2

View File

@ -345,7 +345,10 @@ void command(Context& context, NormalParams)
context.input_handler().prompt( context.input_handler().prompt(
":", "", get_face("Prompt"), ":", "", get_face("Prompt"),
std::bind(&CommandManager::complete, &CommandManager::instance(), _1, _2, _3, _4), [](const Context& context, CompletionFlags flags,
StringView cmd_line, ByteCount pos) {
return CommandManager::instance().complete(context, flags, cmd_line, pos);
},
[](StringView cmdline, PromptEvent event, Context& context) { [](StringView cmdline, PromptEvent event, Context& context) {
if (context.has_ui()) if (context.has_ui())
{ {