diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/client.cc | 32 | ||||
| -rw-r--r-- | src/client.hh | 14 | ||||
| -rw-r--r-- | src/commands.cc | 6 | ||||
| -rw-r--r-- | src/file.cc | 18 | ||||
| -rw-r--r-- | src/file.hh | 5 | ||||
| -rw-r--r-- | src/main.cc | 5 | ||||
| -rw-r--r-- | src/shell_manager.cc | 30 |
7 files changed, 73 insertions, 37 deletions
diff --git a/src/client.cc b/src/client.cc index 611216a7..2fa8e8fb 100644 --- a/src/client.cc +++ b/src/client.cc @@ -1,5 +1,6 @@ #include "client.hh" +#include "clock.hh" #include "context.hh" #include "buffer_utils.hh" #include "debug.hh" @@ -509,4 +510,35 @@ void Client::clear_pending() m_pending_clear = PendingClear::None; } +constexpr std::chrono::seconds wait_timeout{1}; + +BusyIndicator::BusyIndicator(const Context& context, + std::function<DisplayLine(std::chrono::seconds)> status_message, + TimePoint wait_time) + : m_context(context), + m_timer{wait_time + wait_timeout, + [this, status_message = std::move(status_message), wait_time](Timer& timer) { + if (not m_context.has_client()) + return; + using namespace std::chrono; + const auto now = Clock::now(); + timer.set_next_date(now + wait_timeout); + + auto& client = m_context.client(); + if (not m_previous_status) + m_previous_status = client.current_status(); + + client.print_status(status_message(duration_cast<seconds>(now - wait_time))); + client.redraw_ifn(); + }, EventMode::Urgent} {} + +BusyIndicator::~BusyIndicator() +{ + if (m_previous_status and std::uncaught_exceptions() == 0) // restore the status line + { + m_context.print_status(std::move(*m_previous_status)); + m_context.client().redraw_ifn(); + } +} + } diff --git a/src/client.hh b/src/client.hh index 05b091ae..43584c42 100644 --- a/src/client.hh +++ b/src/client.hh @@ -2,6 +2,7 @@ #define client_hh_INCLUDED #include "array.hh" +#include "clock.hh" #include "display_buffer.hh" #include "env_vars.hh" #include "input_handler.hh" @@ -165,6 +166,19 @@ constexpr auto enum_desc(Meta::Type<Autoreload>) }); } +class BusyIndicator +{ +public: + BusyIndicator(const Context& context, + std::function<DisplayLine(std::chrono::seconds)> status_message, + TimePoint wait_time = Clock::now()); + ~BusyIndicator(); +private: + const Context& m_context; + Timer m_timer; + Optional<DisplayLine> m_previous_status; +}; + } #endif // client_hh_INCLUDED diff --git a/src/commands.cc b/src/commands.cc index 90f7a23e..0f892004 100644 --- a/src/commands.cc +++ b/src/commands.cc @@ -618,7 +618,7 @@ void do_write_buffer(Context& context, Optional<String> filename, WriteFlags fla auto method = write_method.value_or_compute([&] { return context.options()["writemethod"].get<WriteMethod>(); }); context.hooks().run_hook(Hook::BufWritePre, effective_filename, context); - write_buffer_to_file(buffer, effective_filename, method, flags); + write_buffer_to_file(context, buffer, effective_filename, method, flags); context.hooks().run_hook(Hook::BufWritePost, effective_filename, context); } @@ -673,7 +673,7 @@ void write_all_buffers(const Context& context, bool sync = false, Optional<Write auto method = write_method.value_or_compute([&] { return context.options()["writemethod"].get<WriteMethod>(); }); auto flags = sync ? WriteFlags::Sync : WriteFlags::None; buffer->run_hook_in_own_context(Hook::BufWritePre, buffer->name(), context.name()); - write_buffer_to_file(*buffer, buffer->name(), method, flags); + write_buffer_to_file(context, *buffer, buffer->name(), method, flags); buffer->run_hook_in_own_context(Hook::BufWritePost, buffer->name(), context.name()); } } @@ -1555,7 +1555,7 @@ const CommandDesc echo_cmd = { message.push_back('\n'); if (auto filename = parser.get_switch("to-file")) - write_to_file(*filename, message); + write_to_file(context, *filename, message); else if (auto command = parser.get_switch("to-shell-script")) ShellManager::instance().eval(*command, context, message, ShellManager::Flags::None, shell_context); else if (parser.get_switch("debug")) diff --git a/src/file.cc b/src/file.cc index 64c9321a..2fbf2e78 100644 --- a/src/file.cc +++ b/src/file.cc @@ -2,6 +2,7 @@ #include "assert.hh" #include "buffer.hh" +#include "client.hh" #include "exception.hh" #include "flags.hh" #include "event_manager.hh" @@ -277,23 +278,28 @@ void write(int fd, StringView data) template void write<true>(int fd, StringView data); template void write<false>(int fd, StringView data); -static int create_file(const char* filename) +static int create_file(const Context& context, const char* filename) { int fd; const int flags = O_CREAT | O_WRONLY | O_TRUNC | (EventManager::has_instance() ? O_NONBLOCK : 0); + using namespace std::chrono; + BusyIndicator busy_indicator{context, [&](seconds elapsed) { + return DisplayLine{format("waiting to open file ({}s)", elapsed.count()), + context.faces()["Information"]}; + }}; while ((fd = open(filename, flags, 0644)) == -1) { if (errno == ENXIO and EventManager::has_instance()) // trying to open a FIFO with no readers yet - EventManager::instance().handle_next_events(EventMode::Urgent, nullptr, std::chrono::nanoseconds{1'000'000}); + EventManager::instance().handle_next_events(EventMode::Urgent, nullptr, nanoseconds{1'000'000}); else return -1; } return fd; } -void write_to_file(StringView filename, StringView data) +void write_to_file(const Context& context, StringView filename, StringView data) { - int fd = create_file(filename.zstr()); + int fd = create_file(context, filename.zstr()); if (fd == -1) throw file_access_error(filename, strerror(errno)); auto close_fd = on_scope_end([fd]{ close(fd); }); @@ -343,7 +349,7 @@ int open_temp_file(StringView filename) return open_temp_file(filename, buffer); } -void write_buffer_to_file(Buffer& buffer, StringView filename, +void write_buffer_to_file(const Context& context, Buffer& buffer, StringView filename, WriteMethod method, WriteFlags flags) { auto zfilename = filename.zstr(); @@ -364,7 +370,7 @@ void write_buffer_to_file(Buffer& buffer, StringView filename, char temp_filename[PATH_MAX]; const int fd = replace ? open_temp_file(filename, temp_filename) - : create_file(zfilename); + : create_file(context, zfilename); if (fd == -1) { auto saved_errno = errno; diff --git a/src/file.hh b/src/file.hh index ead88c43..a0b55e56 100644 --- a/src/file.hh +++ b/src/file.hh @@ -42,7 +42,8 @@ String read_fd(int fd, bool text = false); String read_file(StringView filename, bool text = false); template<bool force_blocking = false> void write(int fd, StringView data); -void write_to_file(StringView filename, StringView data); +class Context; +void write_to_file(const Context&, StringView filename, StringView data); struct MappedFile { @@ -76,7 +77,7 @@ enum class WriteFlags }; constexpr bool with_bit_ops(Meta::Type<WriteFlags>) { return true; } -void write_buffer_to_file(Buffer& buffer, StringView filename, +void write_buffer_to_file(const Context& context, Buffer& buffer, StringView filename, WriteMethod method, WriteFlags flags); void write_buffer_to_fd(Buffer& buffer, int fd); void write_buffer_to_backup_file(Buffer& buffer); diff --git a/src/main.cc b/src/main.cc index e360a6d8..48368ab6 100644 --- a/src/main.cc +++ b/src/main.cc @@ -1007,14 +1007,15 @@ int run_filter(StringView keystr, ConstArrayView<StringView> files, bool quiet, } }; + Context empty_context{Context::EmptyContextFlag{}}; for (auto& file : files) { Buffer* buffer = open_file_buffer(file, Buffer::Flags::NoHooks); if (not suffix_backup.empty()) - write_buffer_to_file(*buffer, buffer->name() + suffix_backup, + write_buffer_to_file(empty_context, *buffer, buffer->name() + suffix_backup, WriteMethod::Overwrite, WriteFlags::None); apply_to_buffer(*buffer); - write_buffer_to_file(*buffer, buffer->name(), + write_buffer_to_file(empty_context, *buffer, buffer->name(), WriteMethod::Overwrite, WriteFlags::None); buffer_manager.delete_buffer(*buffer); } diff --git a/src/shell_manager.cc b/src/shell_manager.cc index 6b656191..0baf77c8 100644 --- a/src/shell_manager.cc +++ b/src/shell_manager.cc @@ -14,6 +14,7 @@ #include "regex.hh" #include <array> +#include <chrono> #include <cstring> #include <sys/types.h> #include <sys/wait.h> @@ -316,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 @@ -373,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 }; } |
