From 5b554ff4749bade238b09f919681aa1d1e050515 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Fri, 26 Jun 2015 13:52:01 +0100 Subject: [PATCH] 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 --- rc/client.kak | 1 + src/command_manager.cc | 36 +++++++++++++++++++++++++++++++++++- src/command_manager.hh | 4 ++++ src/commands.cc | 11 +++++++++++ src/normal.cc | 5 ++++- 5 files changed, 55 insertions(+), 2 deletions(-) diff --git a/rc/client.kak b/rc/client.kak index 5c72a488..69bdde1c 100644 --- a/rc/client.kak +++ b/rc/client.kak @@ -23,6 +23,7 @@ decl str termcmd %sh{ def -docstring 'create a new kak client for current session' \ -shell-params \ + -command-completion \ new %{ %sh{ if [ -z "${kak_opt_termcmd}" ]; then echo "echo -color Error 'termcmd option is not set'" diff --git a/src/command_manager.cc b/src/command_manager.cc index 9ac3a8d4..16ac290c 100644 --- a/src/command_manager.cc +++ b/src/command_manager.cc @@ -506,7 +506,7 @@ Completions CommandManager::complete(const Context& context, } } - // command name completion + // command name completion if (tokens.empty() or (tok_idx == cmd_idx and (tok_idx == tokens.size() or tokens[tok_idx].type() == Token::Type::Raw))) @@ -589,6 +589,40 @@ Completions CommandManager::complete(const Context& context, 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, CompletionFlags flags, CommandParameters params, diff --git a/src/command_manager.hh b/src/command_manager.hh index 152b7253..ee71ea2b 100644 --- a/src/command_manager.hh +++ b/src/command_manager.hh @@ -67,6 +67,10 @@ public: Completions complete(const Context& context, CompletionFlags flags, 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, StringView command_line) const; diff --git a/src/commands.cc b/src/commands.cc index ef818f59..2da6688e 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -798,6 +798,16 @@ void define_command(const ParametersParser& parser, Context& context) 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{}); @@ -816,6 +826,7 @@ const CommandDesc define_command_cmd = { { "file-completion", { false, "complete parameters using filename completion" } }, { "client-completion", { false, "complete parameters using client 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" } } }, ParameterDesc::Flags::None, 2, 2 diff --git a/src/normal.cc b/src/normal.cc index 4cd8dddf..5257908e 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -345,7 +345,10 @@ void command(Context& context, NormalParams) context.input_handler().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) { if (context.has_ui()) {