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;
}
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
@ -190,6 +180,19 @@ struct command_not_found : runtime_error
: 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,
const Context& context,
const EnvVarMap& env_vars)
@ -198,46 +201,32 @@ void CommandManager::execute(const String& command_line,
if (tokens.empty())
return;
TokenList expanded_tokens;
for (auto& token : tokens)
std::vector<String> params;
for (auto it = tokens.begin(); it != tokens.end(); ++it)
{
if (token.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)
if (it->type() == Token::Type::ShellExpand)
{
auto command_it = m_commands.find(begin->content());
if (command_it == m_commands.end())
throw command_not_found(begin->content());
String output = ShellManager::instance().eval(it->content(),
context, env_vars);
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;
for (auto token_it = begin+1; token_it != end; ++token_it)
{
assert(token_it->type() == Token::Type::Raw);
params.push_back(token_it->content());
}
command_it->second.command(params, context);
// when last token is a ShellExpand which produces no output
if (it == tokens.end())
break;
}
if (end == expanded_tokens.end())
break;
begin = end+1;
end = begin;
if (it->type() == Token::Type::CommandSeparator)
{
execute_single_command(params, context);
params.clear();
}
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)

View File

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