Add support for shell script parameters

Now %sh{ ... } can access positional parameters through
standard shell construct, allowing simple handling of variable
parameters.

def command accepts -shell-params flag to use this facility.
This commit is contained in:
Maxime Coste 2012-09-09 17:10:53 +02:00
parent 46565723b1
commit ae76b7dddc
6 changed files with 31 additions and 10 deletions

View File

@ -211,6 +211,7 @@ void CommandManager::execute_single_command(const CommandParameters& params,
void CommandManager::execute(const String& command_line, void CommandManager::execute(const String& command_line,
Context& context, Context& context,
const memoryview<String>& shell_params,
const EnvVarMap& env_vars) const EnvVarMap& env_vars)
{ {
TokenList tokens = parse(command_line); TokenList tokens = parse(command_line);
@ -223,7 +224,8 @@ void CommandManager::execute(const String& command_line,
if (it->type() == Token::Type::ShellExpand) if (it->type() == Token::Type::ShellExpand)
{ {
String output = ShellManager::instance().eval(it->content(), String output = ShellManager::instance().eval(it->content(),
context, env_vars); context, shell_params,
env_vars);
TokenList shell_tokens = parse(output); TokenList shell_tokens = parse(output);
it = tokens.erase(it); it = tokens.erase(it);
for (auto& token : shell_tokens) for (auto& token : shell_tokens)

View File

@ -53,7 +53,8 @@ class CommandManager : public Singleton<CommandManager>
{ {
public: public:
void execute(const String& command_line, Context& context, void execute(const String& command_line, Context& context,
const EnvVarMap& env_vars = EnvVarMap()); const memoryview<String>& shell_params = {},
const EnvVarMap& env_vars = {});
Completions complete(const Context& context, Completions complete(const Context& context,
const String& command_line, CharCount cursor_pos); const String& command_line, CharCount cursor_pos);

View File

@ -534,6 +534,7 @@ void define_command(const CommandParameters& params, Context& context)
{ {
ParametersParser parser(params, ParametersParser parser(params,
{ { "env-params", false }, { { "env-params", false },
{ "shell-params", false },
{ "allow-override", false }, { "allow-override", false },
{ "shell-completion", true } }); { "shell-completion", true } });
@ -552,10 +553,16 @@ void define_command(const CommandParameters& params, Context& context)
if (parser.has_option("env-params")) if (parser.has_option("env-params"))
{ {
cmd = [=](const CommandParameters& params, Context& context) { cmd = [=](const CommandParameters& params, Context& context) {
CommandManager::instance().execute(commands, context, CommandManager::instance().execute(commands, context, {},
params_to_env_var_map(params)); params_to_env_var_map(params));
}; };
} }
if (parser.has_option("shell-params"))
{
cmd = [=](const CommandParameters& params, Context& context) {
CommandManager::instance().execute(commands, context, params, {});
};
}
else else
{ {
cmd = [=](const CommandParameters& params, Context& context) { cmd = [=](const CommandParameters& params, Context& context) {
@ -571,10 +578,11 @@ void define_command(const CommandParameters& params, Context& context)
auto completer = [=](const Context& context, const CommandParameters& params, auto completer = [=](const Context& context, const CommandParameters& params,
size_t token_to_complete, CharCount pos_in_token) size_t token_to_complete, CharCount pos_in_token)
{ {
EnvVarMap vars = params_to_env_var_map(params); EnvVarMap vars = {
vars["token_to_complete"] = int_to_str(token_to_complete); {"token_to_complete", int_to_str(token_to_complete) },
vars["pos_in_token"] = int_to_str((int)pos_in_token); { "pos_in_token", int_to_str((int)pos_in_token) }
String output = ShellManager::instance().eval(shell_cmd, context, vars); };
String output = ShellManager::instance().eval(shell_cmd, context, params, vars);
return split(output, '\n'); return split(output, '\n');
}; };
CommandManager::instance().register_command(cmd_name, cmd, completer); CommandManager::instance().register_command(cmd_name, cmd, completer);

View File

@ -102,7 +102,7 @@ void do_pipe(Context& context)
std::vector<String> strings; std::vector<String> strings;
for (auto& sel : const_cast<const Editor&>(context.editor()).selections()) for (auto& sel : const_cast<const Editor&>(context.editor()).selections())
strings.push_back(ShellManager::instance().pipe(String(sel.begin(), sel.end()), strings.push_back(ShellManager::instance().pipe(String(sel.begin(), sel.end()),
cmdline, context, {})); cmdline, context, {}, {}));
editor.replace(strings); editor.replace(strings);
}); });

View File

@ -16,13 +16,15 @@ ShellManager::ShellManager()
} }
String ShellManager::eval(const String& cmdline, const Context& context, String ShellManager::eval(const String& cmdline, const Context& context,
const memoryview<String>& params,
const EnvVarMap& env_vars) const EnvVarMap& env_vars)
{ {
return pipe("", cmdline, context, env_vars); return pipe("", cmdline, context, params, env_vars);
} }
String ShellManager::pipe(const String& input, String ShellManager::pipe(const String& input,
const String& cmdline, const Context& context, const String& cmdline, const Context& context,
const memoryview<String>& params,
const EnvVarMap& env_vars) const EnvVarMap& env_vars)
{ {
int write_pipe[2]; // child stdin int write_pipe[2]; // child stdin
@ -114,8 +116,14 @@ String ShellManager::pipe(const String& input,
++it; ++it;
} }
std::vector<const char*> execparams = { "sh", "-c", cmdline.c_str() };
if (not params.empty())
execparams.push_back("sh");
for (auto& param : params)
execparams.push_back(param.c_str());
execparams.push_back(NULL);
execlp("sh", "sh", "-c", cmdline.c_str(), NULL); execvp("sh", (char* const*)execparams.data());
exit(-1); exit(-1);
} }
catch (...) { exit(-1); } catch (...) { exit(-1); }

View File

@ -19,10 +19,12 @@ public:
ShellManager(); ShellManager();
String eval(const String& cmdline, const Context& context, String eval(const String& cmdline, const Context& context,
const memoryview<String>& params,
const EnvVarMap& env_vars); const EnvVarMap& env_vars);
String pipe(const String& input, String pipe(const String& input,
const String& cmdline, const Context& context, const String& cmdline, const Context& context,
const memoryview<String>& params,
const EnvVarMap& env_vars); const EnvVarMap& env_vars);
void register_env_var(const String& regex, EnvVarRetriever retriever); void register_env_var(const String& regex, EnvVarRetriever retriever);