From 6548846950598f9173f254fcdf31326aac02bb4f Mon Sep 17 00:00:00 2001 From: Maxime Coste Date: Mon, 13 Mar 2023 20:55:31 +1100 Subject: [PATCH] Slight refactoring of bracketed paste feature Handle begin/end paste directly in paste csi, manage paste buffer out of get_char, filter Key::Invalid earlier. get_next_key returning Key::Invalid means there was some input but it could not be represented as a Key. An empty optional means there was no input at all. --- src/client.cc | 1 + src/input_handler.cc | 3 +- src/terminal_ui.cc | 78 ++++++++++++++++---------------------------- 3 files changed, 30 insertions(+), 52 deletions(-) diff --git a/src/client.cc b/src/client.cc index ec90982c..f022c699 100644 --- a/src/client.cc +++ b/src/client.cc @@ -46,6 +46,7 @@ Client::Client(std::unique_ptr&& ui, m_ui->set_ui_options(m_window->options()["ui_options"].get()); m_ui->set_on_key([this](Key key) { + kak_assert(key != Key::Invalid); if (key == ctrl('c')) { auto prev_handler = set_signal_handler(SIGINT, SIG_IGN); diff --git a/src/input_handler.cc b/src/input_handler.cc index 877517e2..97db92c6 100644 --- a/src/input_handler.cc +++ b/src/input_handler.cc @@ -1750,8 +1750,7 @@ static bool is_valid(Key key) { constexpr Key::Modifiers valid_mods = (Key::Modifiers::Control | Key::Modifiers::Alt | Key::Modifiers::Shift); - return key != Key::Invalid and - ((key.modifiers & ~valid_mods) or key.key <= 0x10FFFF); + return ((key.modifiers & ~valid_mods) or key.key <= 0x10FFFF); } void InputHandler::handle_key(Key key) diff --git a/src/terminal_ui.cc b/src/terminal_ui.cc index 612029e8..13a8af4b 100644 --- a/src/terminal_ui.cc +++ b/src/terminal_ui.cc @@ -447,9 +447,9 @@ TerminalUI::TerminalUI() while (auto key = get_next_key()) { - if (key == ctrl('z')) + if (*key == ctrl('z')) kill(0, SIGTSTP); // We suspend at this line - else + else if (*key != Key::Invalid) m_on_key(*key); } }}, @@ -689,11 +689,7 @@ Optional TerminalUI::get_next_key() return {}; if (unsigned char c = 0; read(STDIN_FILENO, &c, 1) == 1) - { - if (m_paste_buffer) - m_paste_buffer->push_back(c); return c; - } stdin_closed = 1; return {}; @@ -759,16 +755,7 @@ Optional TerminalUI::get_next_key() return mod; }; - enum class PasteEvent { Begin, End }; - struct KeyOrPasteEvent { - KeyOrPasteEvent() = default; - KeyOrPasteEvent(Key key) : key(key) {} - KeyOrPasteEvent(Optional key) : key(key) {} - KeyOrPasteEvent(PasteEvent paste) : paste(paste) {} - const Optional key; - const Optional paste; - }; - auto parse_csi = [this]() -> KeyOrPasteEvent { + auto parse_csi = [this]() -> Optional { auto next_char = [] { return get_char().value_or((unsigned char)0xff); }; int params[16][4] = {}; auto c = next_char(); @@ -878,9 +865,15 @@ Optional TerminalUI::get_next_key() case 33: case 34: return Key{Key::Modifiers::Shift, Key::F9 + params[0][0] - 33}; // rxvt style case 200: - return PasteEvent::Begin; + m_paste_buffer = String{}; + return Key{Key::Invalid}; case 201: - return PasteEvent::End; + if (m_paste_buffer) + { + m_on_paste(*m_paste_buffer); + m_paste_buffer.reset(); + } + return Key{Key::Invalid}; } return {}; case 'u': @@ -962,41 +955,26 @@ Optional TerminalUI::get_next_key() } }; + if (*c == 27) + { + if (auto next = get_char()) + { + if (*next == '[') // potential CSI + return parse_csi().value_or(alt('[')); + if (*next == 'O') // potential SS3 + return parse_ss3().value_or(alt('O')); + return alt(parse_key(*next)); + } + else if (not m_paste_buffer) + return Key{Key::Escape}; + } + if (m_paste_buffer) { - if (*c == 27 and get_char() == '[' and parse_csi().paste == PasteEvent::End) - { - m_paste_buffer->resize(m_paste_buffer->length() - "\033[201~"_str.length(), '\0'); - m_on_paste(*m_paste_buffer); - m_paste_buffer.reset(); - } - return get_next_key(); + m_paste_buffer->push_back(*c); + return Key{Key::Invalid}; } - - if (*c != 27) - return parse_key(*c); - - if (auto next = get_char()) - { - if (*next == 'O') // potential SS3 - return parse_ss3().value_or(alt('O')); - if (*next != '[') - return alt(parse_key(*next)); - // potential CSI - KeyOrPasteEvent csi = parse_csi(); - if (csi.paste == PasteEvent::Begin) - { - m_paste_buffer = String{}; - return get_next_key(); - } - if (csi.paste == PasteEvent::End) // Unmatched bracketed paste sequence. - return {}; - if (csi.key) - return *csi.key; - return alt('['); - } - - return Key{Key::Escape}; + return parse_key(*c); } template