diff --git a/src/command_manager.cc b/src/command_manager.cc index 7419e0bc..ef2fef5c 100644 --- a/src/command_manager.cc +++ b/src/command_manager.cc @@ -609,6 +609,11 @@ Completions CommandManager::complete(const Context& context, return Completions{}; const String& command_name = tokens[cmd_idx].content(); + if (command_name != m_last_complete_command) + { + m_last_complete_command = command_name; + flags |= CompletionFlags::Start; + } auto command_it = find_command(context, command_name); if (command_it == m_commands.end() or @@ -652,6 +657,11 @@ Completions CommandManager::complete(const Context& context, else { const String& command_name = params[0]; + if (command_name != m_last_complete_command) + { + m_last_complete_command = command_name; + flags |= CompletionFlags::Start; + } auto command_it = find_command(context, command_name); if (command_it != m_commands.end() and command_it->second.completer) diff --git a/src/command_manager.hh b/src/command_manager.hh index 4a1c4c01..601629cb 100644 --- a/src/command_manager.hh +++ b/src/command_manager.hh @@ -126,6 +126,8 @@ public: Completions complete_command_name(const Context& context, StringView query, bool with_aliases) const; + void clear_last_complete_command() { m_last_complete_command = String{}; } + private: void execute_single_command(CommandParameters params, Context& context, @@ -143,6 +145,7 @@ private: }; using CommandMap = UnorderedMap; CommandMap m_commands; + String m_last_complete_command; CommandMap::const_iterator find_command(const Context& context, const String& name) const; diff --git a/src/commands.cc b/src/commands.cc index 410752d5..722b25b3 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -843,7 +843,7 @@ void define_command(const ParametersParser& parser, Context& context, const Shel CommandParameters params, size_t token_to_complete, ByteCount pos_in_token) { - if (flags == CompletionFlags::Fast) // no shell on fast completion + if (flags & CompletionFlags::Fast) // no shell on fast completion return Completions{}; ShellContext shell_context{ @@ -866,9 +866,12 @@ void define_command(const ParametersParser& parser, Context& context, const Shel const Context& context, CompletionFlags flags, CommandParameters params, size_t token_to_complete, ByteCount pos_in_token) mutable { + if (flags & CompletionFlags::Start) + token = -1; + if (token != token_to_complete) { - if (flags == CompletionFlags::Fast) // no shell on fast completion + if (flags & CompletionFlags::Fast) // no shell on fast completion return Completions{}; ShellContext shell_context{ @@ -884,9 +887,6 @@ void define_command(const ParametersParser& parser, Context& context, const Shel token = token_to_complete; } - if (token != token_to_complete) - return Completions{}; - StringView query = params[token_to_complete].substr(0, pos_in_token); UsedLetters query_letters = used_letters(query); Vector matches; diff --git a/src/completion.hh b/src/completion.hh index a44f11f3..6743194e 100644 --- a/src/completion.hh +++ b/src/completion.hh @@ -4,6 +4,7 @@ #include #include +#include "flags.hh" #include "units.hh" #include "string.hh" #include "vector.hh" @@ -34,9 +35,13 @@ struct Completions enum class CompletionFlags { - None, - Fast + None = 0, + Fast = 1 << 0, + Start = 1 << 2, }; + +template<> struct WithBitOps : std::true_type {}; + using Completer = std::function; diff --git a/src/normal.cc b/src/normal.cc index 38de574b..0600144e 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -335,6 +335,8 @@ void command(Context& context, NormalParams params) if (not CommandManager::has_instance()) return; + CommandManager::instance().clear_last_complete_command(); + context.input_handler().prompt( ":", "", get_face("Prompt"), false, [](const Context& context, CompletionFlags flags,