command_manager: cleanup command execution, lazy exec shell commands

This commit is contained in:
Maxime Coste 2012-08-06 19:29:51 +02:00
parent 4dc9973288
commit 39797f87dc
2 changed files with 36 additions and 45 deletions

View File

@ -172,16 +172,6 @@ TokenList parse(const String& line,
return result; return result;
} }
void shell_eval(TokenList& params, const String& cmdline,
const Context& context, const EnvVarMap& env_vars)
{
String output = ShellManager::instance().eval(cmdline, context, env_vars);
TokenList tokens = parse(output);
for (auto& token : tokens)
params.push_back(std::move(token));
}
} }
struct command_not_found : runtime_error struct command_not_found : runtime_error
@ -190,6 +180,19 @@ struct command_not_found : runtime_error
: runtime_error(command + " : no such command") {} : runtime_error(command + " : no such command") {}
}; };
void CommandManager::execute_single_command(const CommandParameters& params,
const Context& context) const
{
if (params.empty())
return;
auto command_it = m_commands.find(params[0]);
if (command_it == m_commands.end())
throw command_not_found(params[0]);
memoryview<String> param_view(params.begin()+1, params.end());
command_it->second.command(param_view, context);
}
void CommandManager::execute(const String& command_line, void CommandManager::execute(const String& command_line,
const Context& context, const Context& context,
const EnvVarMap& env_vars) const EnvVarMap& env_vars)
@ -198,46 +201,32 @@ void CommandManager::execute(const String& command_line,
if (tokens.empty()) if (tokens.empty())
return; return;
TokenList expanded_tokens; std::vector<String> params;
for (auto& token : tokens) for (auto it = tokens.begin(); it != tokens.end(); ++it)
{ {
if (token.type() == Token::Type::ShellExpand) if (it->type() == Token::Type::ShellExpand)
shell_eval(expanded_tokens, token.content(),
context, env_vars);
else
expanded_tokens.push_back(token);
}
auto begin = expanded_tokens.begin();
auto end = begin;
while (true)
{
while (end != expanded_tokens.end() and
end->type() != Token::Type::CommandSeparator)
++end;
if (end != begin)
{ {
auto command_it = m_commands.find(begin->content()); String output = ShellManager::instance().eval(it->content(),
if (command_it == m_commands.end()) context, env_vars);
throw command_not_found(begin->content()); TokenList shell_tokens = parse(output);
it = tokens.erase(it);
for (auto& token : shell_tokens)
it = ++tokens.insert(it, std::move(token));
it -= shell_tokens.size();
std::vector<String> params; // when last token is a ShellExpand which produces no output
for (auto token_it = begin+1; token_it != end; ++token_it) if (it == tokens.end())
{ break;
assert(token_it->type() == Token::Type::Raw);
params.push_back(token_it->content());
}
command_it->second.command(params, context);
} }
if (it->type() == Token::Type::CommandSeparator)
if (end == expanded_tokens.end()) {
break; execute_single_command(params, context);
params.clear();
begin = end+1; }
end = begin; if (it->type() == Token::Type::Raw)
params.push_back(it->content());
} }
execute_single_command(params, context);
} }
Completions CommandManager::complete(const String& command_line, size_t cursor_pos) Completions CommandManager::complete(const String& command_line, size_t cursor_pos)

View File

@ -65,6 +65,8 @@ public:
const CommandCompleter& completer = CommandCompleter()); const CommandCompleter& completer = CommandCompleter());
private: private:
void execute_single_command(const CommandParameters& params,
const Context& context) const;
struct CommandDescriptor struct CommandDescriptor
{ {
Command command; Command command;