From a7cac87753d5da2f06545c69911f8b9f6941652f Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Sat, 29 Oct 2016 11:25:58 +0100 Subject: [PATCH] Display a status line message when Kakoune is waiting on a shell to complete If a shell commands takes more than 1s to execute, a message will appear on the status line notifying the user, along with the time Kakoune has been waiting for. --- src/client.cc | 12 ++++++++++-- src/client.hh | 2 +- src/context.cc | 4 ++-- src/context.hh | 2 +- src/shell_manager.cc | 18 ++++++++++++++++-- 5 files changed, 30 insertions(+), 8 deletions(-) diff --git a/src/client.cc b/src/client.cc index 405a82d8..38684524 100644 --- a/src/client.cc +++ b/src/client.cc @@ -98,10 +98,18 @@ void Client::handle_available_input(EventMode mode) } } -void Client::print_status(DisplayLine status_line) +void Client::print_status(DisplayLine status_line, bool immediate) { m_status_line = std::move(status_line); - m_ui_pending |= StatusLine; + if (immediate) + { + m_ui->draw_status(m_status_line, m_mode_line, get_face("StatusLine")); + m_ui->refresh(true); + } + else + { + m_ui_pending |= StatusLine; + } } DisplayLine Client::generate_mode_line() const diff --git a/src/client.hh b/src/client.hh index 1eb845b1..c4633466 100644 --- a/src/client.hh +++ b/src/client.hh @@ -41,7 +41,7 @@ public: void info_show(String title, String content, BufferCoord anchor, InfoStyle style); void info_hide(); - void print_status(DisplayLine status_line); + void print_status(DisplayLine status_line, bool immediate = false); DisplayCoord dimensions() const { return m_ui->dimensions(); } diff --git a/src/context.cc b/src/context.cc index 5e16682d..dc8086fa 100644 --- a/src/context.cc +++ b/src/context.cc @@ -69,10 +69,10 @@ void Context::set_window(Window& window) m_window.reset(&window); } -void Context::print_status(DisplayLine status) const +void Context::print_status(DisplayLine status, bool immediate) const { if (has_client()) - client().print_status(std::move(status)); + client().print_status(std::move(status), immediate); } void JumpList::push(SelectionList jump) diff --git a/src/context.hh b/src/context.hh index f2dfe4d5..a50eb87f 100644 --- a/src/context.hh +++ b/src/context.hh @@ -128,7 +128,7 @@ public: KeymapManager& keymaps() const { return scope().keymaps(); } AliasRegistry& aliases() const { return scope().aliases(); } - void print_status(DisplayLine status) const; + void print_status(DisplayLine status, bool immediate = false) const; StringView main_sel_register_value(StringView reg) const; diff --git a/src/shell_manager.cc b/src/shell_manager.cc index c0943528..2cee4cbe 100644 --- a/src/shell_manager.cc +++ b/src/shell_manager.cc @@ -5,6 +5,8 @@ #include "buffer_utils.hh" #include "event_manager.hh" #include "file.hh" +#include "face_registry.hh" +#include "display_buffer.hh" #include #include @@ -150,7 +152,7 @@ std::pair ShellManager::eval( write(child_stdin.write_fd(), input); child_stdin.close_write_fd(); - auto wait_time = profile ? Clock::now() : Clock::time_point{}; + auto wait_time = Clock::now(); struct PipeReader : FDWatcher { @@ -186,6 +188,10 @@ std::pair ShellManager::eval( // check for termination now that SIGCHLD is blocked bool terminated = waitpid(pid, &status, WNOHANG); + using namespace std::chrono; + static constexpr seconds wait_timeout{1}; + auto next_wait_notification = duration_cast(wait_timeout); + while (not terminated or ((flags & Flags::WaitForStdout) and (child_stdout.read_fd() != -1 or child_stderr.read_fd() != -1))) @@ -193,6 +199,15 @@ std::pair ShellManager::eval( EventManager::instance().handle_next_events(EventMode::Urgent, &orig_mask); if (not terminated) terminated = waitpid(pid, &status, WNOHANG); + + auto wait_duration = Clock::now() - wait_time; + if (wait_duration > next_wait_notification) + { + next_wait_notification = duration_cast(wait_duration + wait_timeout); + context.print_status({ format("waiting for shell command to finish ({}s)", + duration_cast(wait_duration).count()), + get_face("Information") }, true); + } } if (not stderr_contents.empty()) @@ -200,7 +215,6 @@ std::pair ShellManager::eval( if (profile) { - using namespace std::chrono; auto end_time = Clock::now(); auto full = duration_cast(end_time - start_time); auto spawn = duration_cast(wait_time - spawn_time);