Introduce WithRestoredIO (#307)

This function allow running a callback with the terminal hooks
temporarily uninstalled.

Co-authored-by: ArthurSonzogni <sonzogniarthur@gmail.com>
This commit is contained in:
Vladislav Nepogodin
2022-01-19 16:38:39 +04:00
committed by GitHub
parent cd82fccde7
commit b4a655ec65
5 changed files with 93 additions and 14 deletions

View File

@@ -200,7 +200,7 @@ const std::string DeviceStatusReport(DSRMode ps) {
}
using SignalHandler = void(int);
std::stack<std::function<void()>> on_exit_functions;
std::stack<ScreenInteractive::Callback> on_exit_functions;
void OnExit(int signal) {
(void)signal;
while (!on_exit_functions.empty()) {
@@ -211,10 +211,10 @@ void OnExit(int signal) {
auto install_signal_handler = [](int sig, SignalHandler handler) {
auto old_signal_handler = std::signal(sig, handler);
on_exit_functions.push([&]() { std::signal(sig, old_signal_handler); });
on_exit_functions.push([&] { std::signal(sig, old_signal_handler); });
};
std::function<void()> on_resize = [] {};
ScreenInteractive::Callback on_resize = [] {};
void OnResize(int /* signal */) {
on_resize();
}
@@ -230,6 +230,8 @@ class CapturedMouseImpl : public CapturedMouseInterface {
} // namespace
ScreenInteractive* g_active_screen = nullptr;
ScreenInteractive::ScreenInteractive(int dimx,
int dimy,
Dimension dimension,
@@ -275,7 +277,6 @@ CapturedMouse ScreenInteractive::CaptureMouse() {
}
void ScreenInteractive::Loop(Component component) {
static ScreenInteractive* g_active_screen = nullptr;
// Suspend previously active screen:
if (g_active_screen) {
@@ -311,7 +312,22 @@ void ScreenInteractive::Loop(Component component) {
}
}
/// @brief Decorate a function. It executes the same way, but with the currently
/// active screen terminal hooks temporarilly uninstalled during its execution.
/// @param fn The function to decorate.
ScreenInteractive::Callback ScreenInteractive::WithRestoredIO(Callback fn) {
return [this, fn] {
Uninstall();
fn();
Install();
};
}
void ScreenInteractive::Install() {
// After uninstalling the new configuration, flush it to the terminal to
// ensure it is fully applied:
on_exit_functions.push([] { Flush(); });
on_exit_functions.push([this] { ExitLoopClosure()(); });
// Install signal handlers to restore the terminal state on exit. The default
@@ -370,12 +386,6 @@ void ScreenInteractive::Install() {
install_signal_handler(SIGWINCH, OnResize);
#endif
// Commit state:
auto flush = [&] {
Flush();
on_exit_functions.push([] { Flush(); });
};
auto enable = [&](std::vector<DECMode> parameters) {
std::cout << Set(parameters);
on_exit_functions.push([=] { std::cout << Reset(parameters); });
@@ -404,7 +414,9 @@ void ScreenInteractive::Install() {
DECMode::kMouseSgrExtMode,
});
flush();
// After installing the new configuration, flush it to the terminal to ensure
// it is fully applied:
Flush();
quit_ = false;
event_listener_ =
@@ -526,8 +538,8 @@ void ScreenInteractive::Draw(Component component) {
}
}
std::function<void()> ScreenInteractive::ExitLoopClosure() {
return [this]() {
ScreenInteractive::Callback ScreenInteractive::ExitLoopClosure() {
return [this] {
quit_ = true;
event_sender_.reset();
};