From 6b3201f0f1aa7e6bd59f766b29bccc2778555069 Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Fri, 13 Mar 2015 13:39:18 +0000 Subject: [PATCH] Change ShellManager to return both stdout and the return value in a pair --- src/command_manager.cc | 4 ++-- src/commands.cc | 3 ++- src/normal.cc | 20 +++++++++----------- src/shell_manager.cc | 40 ++++++++++++---------------------------- src/shell_manager.hh | 14 ++++---------- 5 files changed, 29 insertions(+), 52 deletions(-) diff --git a/src/command_manager.cc b/src/command_manager.cc index 459fcc22..62018bc8 100644 --- a/src/command_manager.cc +++ b/src/command_manager.cc @@ -310,8 +310,8 @@ String eval_token(const Token& token, Context& context, switch (token.type()) { case Token::Type::ShellExpand: - return ShellManager::instance().eval(content, context, shell_params, - env_vars); + return ShellManager::instance().eval(content, context, {}, + shell_params, env_vars).first; case Token::Type::RegisterExpand: return context.main_sel_register_value(content).str(); case Token::Type::OptionExpand: diff --git a/src/commands.cc b/src/commands.cc index dd6d9878..2ab31021 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -733,7 +733,8 @@ void define_command(const ParametersParser& parser, Context& context) { "token_to_complete", to_string(token_to_complete) }, { "pos_in_token", to_string(pos_in_token) } }; - String output = ShellManager::instance().eval(shell_cmd, context, params, vars); + String output = ShellManager::instance().eval(shell_cmd, context, + {}, params, vars).first; return Completions{ 0_byte, pos_in_token, split(output, '\n', 0) }; }; } diff --git a/src/normal.cc b/src/normal.cc index 4d16bad0..1d4d1cba 100644 --- a/src/normal.cc +++ b/src/normal.cc @@ -393,8 +393,8 @@ void pipe(Context& context, NormalParams) bool insert_eol = str.back() != '\n'; if (insert_eol) str += '\n'; - str = ShellManager::instance().pipe(str, real_cmd, context, - {}, EnvVarMap{}); + str = ShellManager::instance().eval(real_cmd, context, str, + {}, EnvVarMap{}).first; if ((insert_eol or sel.max() == buffer.back_coord()) and str.back() == '\n') str = str.substr(0, str.length()-1).str(); @@ -406,9 +406,9 @@ void pipe(Context& context, NormalParams) else { for (auto& sel : selections) - ShellManager::instance().pipe( - content(buffer, sel), real_cmd, context, {}, - EnvVarMap{}); + ShellManager::instance().eval(real_cmd, context, + content(buffer, sel), + {}, EnvVarMap{}).first; } }); } @@ -435,8 +435,8 @@ void insert_output(Context& context, NormalParams) if (real_cmd.empty()) return; - auto str = ShellManager::instance().eval(real_cmd, context, {}, - EnvVarMap{}); + auto str = ShellManager::instance().eval(real_cmd, context, {}, {}, + EnvVarMap{}).first; ScopedEdition edition(context); context.selections().insert(str, mode); }); @@ -783,10 +783,8 @@ void keep_pipe(Context& context, NormalParams) Vector keep; for (auto& sel : context.selections()) { - int status = 0; - shell_manager.pipe(content(buffer, sel), cmdline, context, - {}, EnvVarMap{}, &status); - if (status == 0) + if (shell_manager.eval(cmdline, context, content(buffer, sel), + {}, EnvVarMap{}).second == 0) keep.push_back(sel); } if (keep.empty()) diff --git a/src/shell_manager.cc b/src/shell_manager.cc index 0e5760ed..4dcb7eef 100644 --- a/src/shell_manager.cc +++ b/src/shell_manager.cc @@ -26,19 +26,9 @@ ShellManager::ShellManager() setenv("PATH", new_path.c_str(), 1); } -String ShellManager::eval(StringView cmdline, const Context& context, - ConstArrayView params, - const EnvVarMap& env_vars, - int* exit_status) -{ - return pipe("", cmdline, context, params, env_vars, exit_status); -} - -String ShellManager::pipe(StringView input, - StringView cmdline, const Context& context, - ConstArrayView params, - const EnvVarMap& env_vars, - int* exit_status) +std::pair ShellManager::eval( + StringView cmdline, const Context& context, StringView input, + ConstArrayView params, const EnvVarMap& env_vars) { int write_pipe[2]; // child stdin int read_pipe[2]; // child stdout @@ -48,7 +38,6 @@ String ShellManager::pipe(StringView input, ::pipe(read_pipe); ::pipe(error_pipe); - String output; if (pid_t pid = fork()) { close(write_pipe[0]); @@ -58,7 +47,7 @@ String ShellManager::pipe(StringView input, write(write_pipe[1], input.data(), (int)input.length()); close(write_pipe[1]); - String error; + String stdout, stderr; { auto pipe_reader = [](String& output) { return [&output](FDWatcher& watcher, EventMode) { @@ -70,24 +59,19 @@ String ShellManager::pipe(StringView input, }; }; - FDWatcher stdout_watcher{read_pipe[0], pipe_reader(output)}; - FDWatcher stderr_watcher{error_pipe[0], pipe_reader(error)}; + FDWatcher stdout_watcher{read_pipe[0], pipe_reader(stdout)}; + FDWatcher stderr_watcher{error_pipe[0], pipe_reader(stderr)}; while (not stdout_watcher.closed() or not stderr_watcher.closed()) EventManager::instance().handle_next_events(EventMode::Urgent); } - if (not error.empty()) - write_debug("shell stderr: <<<\n" + error + ">>>"); + if (not stderr.empty()) + write_debug("shell stderr: <<<\n" + stderr + ">>>"); - waitpid(pid, exit_status, 0); - if (exit_status) - { - if (WIFEXITED(*exit_status)) - *exit_status = WEXITSTATUS(*exit_status); - else - *exit_status = -1; - } + int status = 0; + waitpid(pid, &status, 0); + return { stdout, WIFEXITED(status) ? WEXITSTATUS(status) : - 1 }; } else try { @@ -131,7 +115,7 @@ String ShellManager::pipe(StringView input, exit(-1); } catch (...) { exit(-1); } - return output; + return {}; } void ShellManager::register_env_var(StringView regex, diff --git a/src/shell_manager.hh b/src/shell_manager.hh index 60b9b13f..fde507b6 100644 --- a/src/shell_manager.hh +++ b/src/shell_manager.hh @@ -20,16 +20,10 @@ class ShellManager : public Singleton public: ShellManager(); - String eval(StringView cmdline, const Context& context, - ConstArrayView params, - const EnvVarMap& env_vars, - int* exit_status = nullptr); - - String pipe(StringView input, - StringView cmdline, const Context& context, - ConstArrayView params, - const EnvVarMap& env_vars, - int* exit_status = nullptr); + std::pair eval(StringView cmdline, const Context& context, + StringView input = {}, + ConstArrayView params = {}, + const EnvVarMap& env_vars = EnvVarMap{}); void register_env_var(StringView regex, EnvVarRetriever retriever); String get_val(StringView name, const Context& context) const;