diff options
Diffstat (limited to 'src/shell_manager.cc')
| -rw-r--r-- | src/shell_manager.cc | 49 |
1 files changed, 17 insertions, 32 deletions
diff --git a/src/shell_manager.cc b/src/shell_manager.cc index 47432df5..0baf77c8 100644 --- a/src/shell_manager.cc +++ b/src/shell_manager.cc @@ -1,6 +1,6 @@ #include "shell_manager.hh" -#include "buffer_utils.hh" +#include "debug.hh" #include "client.hh" #include "clock.hh" #include "context.hh" @@ -10,11 +10,11 @@ #include "face_registry.hh" #include "file.hh" #include "flags.hh" -#include "option.hh" #include "option_types.hh" #include "regex.hh" #include <array> +#include <chrono> #include <cstring> #include <sys/types.h> #include <sys/wait.h> @@ -118,7 +118,7 @@ Shell spawn_shell(const char* shell, StringView cmdline, if (pid_t pid = vfork()) return {pid, std::move(stdin_pipe[1]), std::move(stdout_pipe[0]), std::move(stderr_pipe[0])}; - auto renamefd = [](int oldfd, int newfd) { + constexpr auto renamefd = [](int oldfd, int newfd) { if (oldfd == newfd) return; dup2(oldfd, newfd); @@ -198,18 +198,22 @@ FDWatcher make_reader(int fd, String& contents, OnClose&& on_close) }}; } -FDWatcher make_pipe_writer(UniqueFd& fd, StringView contents) +FDWatcher make_pipe_writer(UniqueFd& fd, const FunctionRef<StringView ()>& generator) { int flags = fcntl((int)fd, F_GETFL, 0); fcntl((int)fd, F_SETFL, flags | O_NONBLOCK); return {(int)fd, FdEvents::Write, EventMode::Urgent, - [contents, &fd](FDWatcher& watcher, FdEvents, EventMode) mutable { + [&generator, &fd, contents=generator()](FDWatcher& watcher, FdEvents, EventMode) mutable { while (fd_writable((int)fd)) { ssize_t size = ::write((int)fd, contents.begin(), (size_t)contents.length()); if (size > 0) + { contents = contents.substr(ByteCount{(int)size}); + if (contents.empty()) + contents = generator(); + } if (size == -1 and (errno == EAGAIN or errno == EWOULDBLOCK)) return; if (size < 0 or contents.empty()) @@ -264,7 +268,7 @@ struct CommandFifos } std::pair<String, int> ShellManager::eval( - StringView cmdline, const Context& context, StringView input, + StringView cmdline, const Context& context, FunctionRef<StringView ()> input_generator, Flags flags, const ShellContext& shell_context) { const DebugFlags debug_flags = context.options()["debug"].get<DebugFlags>(); @@ -291,13 +295,13 @@ std::pair<String, int> ShellManager::eval( }); auto spawn_time = profile ? Clock::now() : Clock::time_point{}; - auto shell = spawn_shell(m_shell.c_str(), cmdline, shell_context.params, kak_env, not input.empty()); + auto shell = spawn_shell(m_shell.c_str(), cmdline, shell_context.params, kak_env, true); auto wait_time = Clock::now(); String stdout_contents, stderr_contents; auto stdout_reader = make_reader((int)shell.out, stdout_contents, [&](bool){ shell.out.close(); }); auto stderr_reader = make_reader((int)shell.err, stderr_contents, [&](bool){ shell.err.close(); }); - auto stdin_writer = make_pipe_writer(shell.in, input); + auto stdin_writer = make_pipe_writer(shell.in, input_generator); // block SIGCHLD to make sure we wont receive it before // our call to pselect, that will end up blocking indefinitly. @@ -313,24 +317,11 @@ std::pair<String, int> ShellManager::eval( bool failed = false; using namespace std::chrono; - static constexpr seconds wait_timeout{1}; - Optional<DisplayLine> previous_status; - Timer wait_timer{wait_time + wait_timeout, [&](Timer& timer) { - if (not context.has_client()) - return; - - const auto now = Clock::now(); - timer.set_next_date(now + wait_timeout); - auto& client = context.client(); - if (not previous_status) - previous_status = client.current_status(); - - client.print_status({format("waiting for shell command to finish{} ({}s)", - terminated ? " (shell terminated)" : "", - duration_cast<seconds>(now - wait_time).count()), - context.faces()[failed ? "Error" : "Information"]}); - client.redraw_ifn(); - }, EventMode::Urgent}; + BusyIndicator busy_indicator{context, [&](seconds elapsed) { + return DisplayLine{format("waiting for shell command to finish{} ({}s)", + terminated ? " (shell terminated)" : "", elapsed.count()), + context.faces()[failed ? "Error" : "Information"]}; + }}; bool cancelling = false; while (not terminated or shell.in or @@ -370,12 +361,6 @@ std::pair<String, int> ShellManager::eval( if (cancelling) throw cancel{}; - if (previous_status) // restore the status line - { - context.print_status(std::move(*previous_status)); - context.client().redraw_ifn(); - } - return { std::move(stdout_contents), WIFEXITED(status) ? WEXITSTATUS(status) : -1 }; } |
