summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client.cc32
-rw-r--r--src/client.hh14
-rw-r--r--src/commands.cc6
-rw-r--r--src/file.cc18
-rw-r--r--src/file.hh5
-rw-r--r--src/main.cc5
-rw-r--r--src/shell_manager.cc30
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 };
}