From 6dd7c742c647d698cae3a9b51269caff4fe57ee5 Mon Sep 17 00:00:00 2001 From: Andrzej Rybczak Date: Thu, 30 Oct 2014 23:47:31 +0100 Subject: [PATCH] window: support early exit from the readline prompt with Ctrl-{C,G} --- src/ncmpcpp.cpp | 4 ++++ src/window.cpp | 18 +++++++++++++++++- src/window.h | 14 ++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/ncmpcpp.cpp b/src/ncmpcpp.cpp index db7d7007..4a5657c5 100644 --- a/src/ncmpcpp.cpp +++ b/src/ncmpcpp.cpp @@ -226,6 +226,10 @@ int main(int argc, char **argv) { Statusbar::printf("Error: %1%", e.errorMessage()); } + catch (NC::PromptAborted &) + { + Statusbar::printf("Action aborted"); + } if (myScreen == myPlaylist) myPlaylist->EnableHighlighting(); diff --git a/src/window.cpp b/src/window.cpp index 961fcd59..9edc377d 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -40,6 +40,8 @@ namespace { namespace rl { +bool aborted; + NC::Window *w; size_t start_x; size_t start_y; @@ -380,12 +382,22 @@ void initScreen(GNUC_UNUSED const char *window_title, bool enable_colors) noecho(); curs_set(0); - rl_initialize(); // disable autocompletion rl_attempted_completion_function = [](const char *, int, int) -> char ** { rl_attempted_completion_over = 1; return nullptr; }; + auto abort_prompt = [](int, int) -> int { + rl::aborted = true; + rl_done = 1; + return 0; + }; + // if ctrl-c or ctrl-g is pressed, abort the prompt + rl_bind_key(KEY_CTRL_C, abort_prompt); + rl_bind_key(KEY_CTRL_G, abort_prompt); + // do not change the state of the terminal + rl_prep_term_function = nullptr; + rl_deprep_term_function = nullptr; // do not catch signals rl_catch_signals = 0; // overwrite readline callbacks @@ -796,6 +808,7 @@ void Window::pushChar(int ch) std::string Window::getString(const std::string &base, size_t width, bool encrypted) { + rl::aborted = false; rl::w = this; getyx(m_window, rl::start_y, rl::start_x); rl::width = width; @@ -826,6 +839,9 @@ std::string Window::getString(const std::string &base, size_t width, bool encryp free(input); } + if (rl::aborted) + throw PromptAborted(std::move(result)); + return result; } diff --git a/src/window.h b/src/window.h index b769e16f..6e9dcc10 100644 --- a/src/window.h +++ b/src/window.h @@ -112,6 +112,20 @@ /// wrappers over original curses library namespace NC {// +/// Thrown if Ctrl-G is pressed during the call to Window::getString(). +/// @see Window::getString() +struct PromptAborted : std::exception +{ + template + PromptAborted(ArgT &&prompt) + : m_prompt(std::forward(prompt)) { } + + virtual const char *what() const noexcept OVERRIDE { return m_prompt.c_str(); } + +private: + std::string m_prompt; +}; + /// Colors used by NCurses enum class Color { Default, Black, Red, Green, Yellow, Blue, Magenta, Cyan, White, End };