summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/command_manager.cc96
-rw-r--r--src/command_manager.hh30
-rw-r--r--src/commands.cc21
-rw-r--r--src/completion.hh1
-rw-r--r--src/normal.cc8
5 files changed, 75 insertions, 81 deletions
diff --git a/src/command_manager.cc b/src/command_manager.cc
index c3eb141e..f7d094bb 100644
--- a/src/command_manager.cc
+++ b/src/command_manager.cc
@@ -719,10 +719,34 @@ static Completions complete_expand(const Context& context, CompletionFlags flags
return {};
}
-Completions CommandManager::complete(const Context& context,
- CompletionFlags flags,
- StringView command_line,
- ByteCount cursor_pos)
+
+static Completions requote(Completions completions, Token::Type token_type)
+{
+ if (completions.flags & Completions::Flags::Quoted)
+ return completions;
+
+ if (token_type == Token::Type::Raw)
+ {
+ const bool at_token_start = completions.start == 0;
+ for (auto& candidate : completions.candidates)
+ {
+ const StringView to_escape = ";\n \t";
+ if ((at_token_start and candidate.substr(0_byte, 1_byte) == "%") or
+ any_of(candidate, [&](auto c) { return contains(to_escape, c); }))
+ candidate = at_token_start ? quote(candidate) : escape(candidate, to_escape, '\\');
+ }
+ }
+ else if (token_type == Token::Type::RawQuoted)
+ completions.flags |= Completions::Flags::Quoted;
+ else
+ kak_assert(false);
+
+ return completions;
+}
+
+Completions CommandManager::Completer::operator()(
+ const Context& context, CompletionFlags flags,
+ StringView command_line, ByteCount cursor_pos)
{
auto prefix = command_line.substr(0_byte, cursor_pos);
CommandParser parser{prefix};
@@ -754,29 +778,6 @@ Completions CommandManager::complete(const Context& context,
if (token.terminated) // do not complete past explicit token close
return Completions{};
- auto requote = [](Completions completions, Token::Type token_type) {
- if (completions.flags & Completions::Flags::Quoted)
- return completions;
-
- if (token_type == Token::Type::Raw)
- {
- const bool at_token_start = completions.start == 0;
- for (auto& candidate : completions.candidates)
- {
- const StringView to_escape = ";\n \t";
- if ((at_token_start and candidate.substr(0_byte, 1_byte) == "%") or
- any_of(candidate, [&](auto c) { return contains(to_escape, c); }))
- candidate = at_token_start ? quote(candidate) : escape(candidate, to_escape, '\\');
- }
- }
- else if (token_type == Token::Type::RawQuoted)
- completions.flags |= Completions::Flags::Quoted;
- else
- kak_assert(false);
-
- return completions;
- };
-
const ByteCount start = token.pos;
const ByteCount pos_in_token = cursor_pos - start;
@@ -784,9 +785,11 @@ Completions CommandManager::complete(const Context& context,
if (tokens.size() == 1 and (token.type == Token::Type::Raw or
token.type == Token::Type::RawQuoted))
{
- return offset_pos(requote(complete_command_name(context, prefix), token.type), start);
+ return offset_pos(requote(CommandManager::instance().complete_command_name(context, prefix), token.type), start);
}
+ auto& commands = CommandManager::instance().m_commands;
+
switch (token.type)
{
case Token::Type::RegisterExpand:
@@ -800,18 +803,17 @@ Completions CommandManager::complete(const Context& context,
case Token::Type::RawQuoted:
{
StringView command_name = tokens.front().content;
+ auto command_it = commands.find(resolve_alias(context, command_name));
+ if (command_it == commands.end())
+ return Completions{};
+
+ auto& command = command_it->value;
if (command_name != m_last_complete_command)
{
m_last_complete_command = command_name.str();
- flags |= CompletionFlags::Start;
+ m_command_completer = command.completer;
}
- auto command_it = m_commands.find(resolve_alias(context, command_name));
- if (command_it == m_commands.end())
- return Completions{};
-
- auto& command = command_it->value;
-
auto raw_params = tokens | skip(1) | transform(&Token::content) | gather<Vector<String>>();
ParametersParser parser{raw_params, command.param_desc, true};
@@ -841,13 +843,13 @@ Completions CommandManager::complete(const Context& context,
break;
}
- if (not command.completer)
+ if (not m_command_completer)
return Completions{};
Vector<String> params{parser.begin(), parser.end()};
auto index = params.size() - 1;
- return offset_pos(requote(command.completer(context, flags, params, index, pos_in_token), token.type), start);
+ return offset_pos(requote(m_command_completer(context, flags, params, index, pos_in_token), token.type), start);
}
case Token::Type::Expand:
return complete_expand(context, flags, token.content, start, cursor_pos, pos_in_token);
@@ -857,26 +859,26 @@ 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)
+Completions CommandManager::NestedCompleter::operator()(
+ 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)
- return complete_command_name(context, prefix);
+ return CommandManager::instance().complete_command_name(context, prefix);
StringView command_name = params[0];
+ auto& commands = CommandManager::instance().m_commands;
if (command_name != m_last_complete_command)
{
m_last_complete_command = command_name.str();
- flags |= CompletionFlags::Start;
+ auto it = commands.find(resolve_alias(context, command_name));
+ if (it != commands.end())
+ m_command_completer = it->value.completer;
}
- auto it = m_commands.find(resolve_alias(context, command_name));
- return (it != m_commands.end() and it->value.completer)
- ? it->value.completer(context, flags, params.subrange(1), token_to_complete-1, pos_in_token)
+ return m_command_completer
+ ? m_command_completer(context, flags, params.subrange(1), token_to_complete-1, pos_in_token)
: Completions{};
}
diff --git a/src/command_manager.hh b/src/command_manager.hh
index 8804b5b2..878ca129 100644
--- a/src/command_manager.hh
+++ b/src/command_manager.hh
@@ -93,13 +93,6 @@ public:
const ShellContext& shell_context);
- 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);
-
Optional<CommandInfo> command_info(const Context& context,
StringView command_line) const;
@@ -116,8 +109,6 @@ public:
Completions complete_command_name(const Context& context, StringView query) const;
- void clear_last_complete_command() { m_last_complete_command = String{}; }
-
bool module_defined(StringView module_name) const;
void register_module(String module_name, String commands);
@@ -127,6 +118,26 @@ public:
Completions complete_module_name(StringView query) const;
+ struct Completer
+ {
+ Completions operator()(const Context& context, CompletionFlags flags,
+ StringView command_line, ByteCount cursor_pos);
+
+ private:
+ String m_last_complete_command;
+ CommandCompleter m_command_completer;
+ };
+
+ struct NestedCompleter
+ {
+ Completions operator()(const Context& context, CompletionFlags flags,
+ CommandParameters params, size_t token_to_complete, ByteCount pos_in_token);
+
+ private:
+ String m_last_complete_command;
+ CommandCompleter m_command_completer;
+ };
+
private:
struct Command
{
@@ -139,7 +150,6 @@ private:
};
using CommandMap = HashMap<String, Command, MemoryDomain::Commands>;
CommandMap m_commands;
- String m_last_complete_command;
int m_command_depth = 0;
struct Module
diff --git a/src/commands.cc b/src/commands.cc
index 94c61241..92e11e1b 100644
--- a/src/commands.cc
+++ b/src/commands.cc
@@ -80,7 +80,7 @@ struct PerArgumentCommandCompleter<Completer, Rest...> : PerArgumentCommandCompl
Completions operator()(const Context& context, CompletionFlags flags,
CommandParameters params, size_t token_to_complete,
- ByteCount pos_in_token) const
+ ByteCount pos_in_token)
{
if (token_to_complete == 0)
{
@@ -284,9 +284,6 @@ struct ShellCandidatesCompleter
CommandParameters params, size_t token_to_complete,
ByteCount pos_in_token)
{
- if (flags & CompletionFlags::Start)
- m_token = -1;
-
if (m_token != token_to_complete)
{
ShellContext shell_context{
@@ -1140,11 +1137,7 @@ const CommandDesc add_hook_cmd = {
},
CommandFlags::None,
CommandHelper{},
- make_completer(menu(complete_scope), menu(complete_hooks), complete_nothing,
- [](const Context& context, CompletionFlags flags,
- StringView prefix, ByteCount cursor_pos)
- { return CommandManager::instance().complete(
- context, flags, prefix, cursor_pos); }),
+ make_completer(menu(complete_scope), menu(complete_hooks), complete_nothing, CommandManager::Completer{}),
[](const ParametersParser& parser, Context& context, const ShellContext&)
{
auto descs = enum_desc(Meta::Type<Hook>{});
@@ -1270,15 +1263,7 @@ CommandCompleter make_command_completer(StringView type, StringView param, Compl
return ShellCandidatesCompleter{param.str(), completions_flags};
}
else if (type == "command")
- {
- return [](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);
- };
- }
+ return CommandManager::NestedCompleter{};
else if (type == "shell")
{
return [=](const Context& context, CompletionFlags flags,
diff --git a/src/completion.hh b/src/completion.hh
index d3aeca2b..e9321d5a 100644
--- a/src/completion.hh
+++ b/src/completion.hh
@@ -47,7 +47,6 @@ enum class CompletionFlags
{
None = 0,
Fast = 1 << 0,
- Start = 1 << 2,
};
constexpr bool with_bit_ops(Meta::Type<CompletionFlags>) { return true; }
diff --git a/src/normal.cc b/src/normal.cc
index ebe86ebc..e70d0680 100644
--- a/src/normal.cc
+++ b/src/normal.cc
@@ -471,17 +471,15 @@ void command(const Context& context, EnvVarMap env_vars, char reg = 0)
if (not CommandManager::has_instance())
throw runtime_error{"commands are not supported"};
- CommandManager::instance().clear_last_complete_command();
-
String default_command = context.main_sel_register_value(reg ? reg : ':').str();
context.input_handler().prompt(
":", {}, default_command,
context.faces()["Prompt"], PromptFlags::DropHistoryEntriesWithBlankPrefix,
':',
- [](const Context& context, CompletionFlags flags,
- StringView cmd_line, ByteCount pos) {
- return CommandManager::instance().complete(context, flags, cmd_line, pos);
+ [completer=CommandManager::Completer{}](const Context& context, CompletionFlags flags,
+ StringView cmd_line, ByteCount pos) mutable {
+ return completer(context, flags, cmd_line, pos);
},
[env_vars = std::move(env_vars), default_command](StringView cmdline, PromptEvent event, Context& context) {
if (context.has_client())