From ae76b7dddc2973b809109329aabf15fdd676b7d6 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Sun, 9 Sep 2012 17:10:53 +0200 Subject: [PATCH] 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. --- src/command_manager.cc | 4 +++- src/command_manager.hh | 3 ++- src/commands.cc | 18 +++++++++++++----- src/main.cc | 2 +- src/shell_manager.cc | 12 ++++++++++-- src/shell_manager.hh | 2 ++ 6 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/command_manager.cc b/src/command_manager.cc index 1110583f..df23ca6e 100644 --- a/src/command_manager.cc +++ b/src/command_manager.cc @@ -211,6 +211,7 @@ void CommandManager::execute_single_command(const CommandParameters& params, void CommandManager::execute(const String& command_line, Context& context, + const memoryview& shell_params, const EnvVarMap& env_vars) { TokenList tokens = parse(command_line); @@ -223,7 +224,8 @@ void CommandManager::execute(const String& command_line, if (it->type() == Token::Type::ShellExpand) { String output = ShellManager::instance().eval(it->content(), - context, env_vars); + context, shell_params, + env_vars); TokenList shell_tokens = parse(output); it = tokens.erase(it); for (auto& token : shell_tokens) diff --git a/src/command_manager.hh b/src/command_manager.hh index cbc6a2c7..84f764ee 100644 --- a/src/command_manager.hh +++ b/src/command_manager.hh @@ -53,7 +53,8 @@ class CommandManager : public Singleton { public: void execute(const String& command_line, Context& context, - const EnvVarMap& env_vars = EnvVarMap()); + const memoryview& shell_params = {}, + const EnvVarMap& env_vars = {}); Completions complete(const Context& context, const String& command_line, CharCount cursor_pos); diff --git a/src/commands.cc b/src/commands.cc index 60a9f5f2..07a62c69 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -534,6 +534,7 @@ void define_command(const CommandParameters& params, Context& context) { ParametersParser parser(params, { { "env-params", false }, + { "shell-params", false }, { "allow-override", false }, { "shell-completion", true } }); @@ -552,10 +553,16 @@ void define_command(const CommandParameters& params, Context& context) if (parser.has_option("env-params")) { cmd = [=](const CommandParameters& params, Context& context) { - CommandManager::instance().execute(commands, context, + CommandManager::instance().execute(commands, context, {}, 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 { 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, size_t token_to_complete, CharCount pos_in_token) { - EnvVarMap vars = params_to_env_var_map(params); - vars["token_to_complete"] = int_to_str(token_to_complete); - vars["pos_in_token"] = int_to_str((int)pos_in_token); - String output = ShellManager::instance().eval(shell_cmd, context, vars); + EnvVarMap vars = { + {"token_to_complete", int_to_str(token_to_complete) }, + { "pos_in_token", int_to_str((int)pos_in_token) } + }; + String output = ShellManager::instance().eval(shell_cmd, context, params, vars); return split(output, '\n'); }; CommandManager::instance().register_command(cmd_name, cmd, completer); diff --git a/src/main.cc b/src/main.cc index 5574327e..8dd9e30b 100644 --- a/src/main.cc +++ b/src/main.cc @@ -102,7 +102,7 @@ void do_pipe(Context& context) std::vector strings; for (auto& sel : const_cast(context.editor()).selections()) strings.push_back(ShellManager::instance().pipe(String(sel.begin(), sel.end()), - cmdline, context, {})); + cmdline, context, {}, {})); editor.replace(strings); }); diff --git a/src/shell_manager.cc b/src/shell_manager.cc index cb6e94c7..f35b3ddc 100644 --- a/src/shell_manager.cc +++ b/src/shell_manager.cc @@ -16,13 +16,15 @@ ShellManager::ShellManager() } String ShellManager::eval(const String& cmdline, const Context& context, + const memoryview& params, const EnvVarMap& env_vars) { - return pipe("", cmdline, context, env_vars); + return pipe("", cmdline, context, params, env_vars); } String ShellManager::pipe(const String& input, const String& cmdline, const Context& context, + const memoryview& params, const EnvVarMap& env_vars) { int write_pipe[2]; // child stdin @@ -114,8 +116,14 @@ String ShellManager::pipe(const String& input, ++it; } + std::vector 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); } catch (...) { exit(-1); } diff --git a/src/shell_manager.hh b/src/shell_manager.hh index 6ce3aada..615b19ec 100644 --- a/src/shell_manager.hh +++ b/src/shell_manager.hh @@ -19,10 +19,12 @@ public: ShellManager(); String eval(const String& cmdline, const Context& context, + const memoryview& params, const EnvVarMap& env_vars); String pipe(const String& input, const String& cmdline, const Context& context, + const memoryview& params, const EnvVarMap& env_vars); void register_env_var(const String& regex, EnvVarRetriever retriever);