From aeaf39b8ea705e701e0bc8235214a093fff12cfe Mon Sep 17 00:00:00 2001 From: Arthur Sonzogni Date: Tue, 18 Oct 2022 22:58:22 +0200 Subject: [PATCH] Fix F1-F4 keymapping. (#501) It was just wrong, even on Linux. Bug:https://github.com/ArthurSonzogni/FTXUI/issues/492 --- CHANGELOG.md | 3 +- examples/component/print_key_press.cpp | 64 ++++++++++++++++++- src/ftxui/component/event.cpp | 26 ++++---- src/ftxui/component/input.cpp | 2 +- src/ftxui/component/terminal_input_parser.cpp | 29 +++++---- .../component/terminal_input_parser_test.cpp | 10 +-- 6 files changed, 104 insertions(+), 30 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 29a6ae9..b594d5b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,8 @@ current (development) - Feature: `Input` supports CTRL+Left and CTRL+Right - Improvement: The `Menu` keeps the focus when an entry is selected with the mouse. -- Bug: Add implementation of `ButtonOption::Border()`. It was missing. +- Bugfix: Add implementation of `ButtonOption::Border()`. It was missing. +- Bugfix: Provide the correct key for F1-F4 and F11. ### Screen - Feature: add `Box::Union(a,b) -> Box` diff --git a/examples/component/print_key_press.cpp b/examples/component/print_key_press.cpp index 8bcb119..a42f2a4 100644 --- a/examples/component/print_key_press.cpp +++ b/examples/component/print_key_press.cpp @@ -25,7 +25,7 @@ std::string Stringify(Event event) { out = "(" + out + " ) -> "; if (event.is_character()) { - out += "character(" + event.character() + ")"; + out += "Event::Character(\"" + event.character() + "\")"; } else if (event.is_mouse()) { out += "mouse"; switch (event.mouse().button) { @@ -66,6 +66,68 @@ std::string Stringify(Event event) { out += "(" + // std::to_string(event.mouse().x) + "," + std::to_string(event.mouse().y) + ")"; + } else if (event == Event::ArrowLeft) { + out += "Event::ArrowLeft"; + } else if (event == Event::ArrowRight) { + out += "Event::ArrowRight"; + } else if (event == Event::ArrowUp) { + out += "Event::ArrowUp"; + } else if (event == Event::ArrowDown) { + out += "Event::ArrowDown"; + } else if (event == Event::ArrowLeftCtrl) { + out += "Event::ArrowLeftCtrl"; + } else if (event == Event ::ArrowRightCtrl) { + out += "Event::ArrowRightCtrl"; + } else if (event == Event::ArrowUpCtrl) { + out += "Event::ArrowUpCtrl"; + } else if (event == Event::ArrowDownCtrl) { + out += "Event::ArrowDownCtrl"; + } else if (event == Event::Backspace) { + out += "Event::Backspace"; + } else if (event == Event::Delete) { + out += "Event::Delete"; + } else if (event == Event::Escape) { + out += "Event::Escape"; + } else if (event == Event::Return) { + out += "Event::Return"; + } else if (event == Event::Tab) { + out += "Event::Tab"; + } else if (event == Event::TabReverse) { + out += "Event::TabReverse"; + } else if (event == Event::F1) { + out += "Event::F1"; + } else if (event == Event::F2) { + out += "Event::F2"; + } else if (event == Event::F3) { + out += "Event::F3"; + } else if (event == Event::F4) { + out += "Event::F4"; + } else if (event == Event::F5) { + out += "Event::F5"; + } else if (event == Event::F6) { + out += "Event::F6"; + } else if (event == Event::F7) { + out += "Event::F7"; + } else if (event == Event::F8) { + out += "Event::F8"; + } else if (event == Event::F9) { + out += "Event::F9"; + } else if (event == Event::F10) { + out += "Event::F10"; + } else if (event == Event::F11) { + out += "Event::F11"; + } else if (event == Event::F12) { + out += "Event::F12"; + } else if (event == Event::Home) { + out += "Event::Home"; + } else if (event == Event::End) { + out += "Event::End"; + } else if (event == Event::PageUp) { + out += "Event::PageUp"; + } else if (event == Event::PageDown) { + out += "Event::PageDown"; + } else if (event == Event::Custom) { + out += "Custom"; } else { out += "(special)"; } diff --git a/src/ftxui/component/event.cpp b/src/ftxui/component/event.cpp index 57d746a..1cd95ed 100644 --- a/src/ftxui/component/event.cpp +++ b/src/ftxui/component/event.cpp @@ -65,18 +65,22 @@ const Event Event::Escape = Event::Special("\x1B"); // NOLINT const Event Event::Return = Event::Special({10}); // NOLINT const Event Event::Tab = Event::Special({9}); // NOLINT const Event Event::TabReverse = Event::Special({27, 91, 90}); // NOLINT -const Event Event::F1 = Event::Special("\x1B[OP"); // NOLINT -const Event Event::F2 = Event::Special("\x1B[OQ"); // NOLINT -const Event Event::F3 = Event::Special("\x1B[OR"); // NOLINT -const Event Event::F4 = Event::Special("\x1B[OS"); // NOLINT -const Event Event::F5 = Event::Special("\x1B[15~"); // NOLINT -const Event Event::F6 = Event::Special("\x1B[17~"); // NOLINT -const Event Event::F7 = Event::Special("\x1B[18~"); // NOLINT -const Event Event::F8 = Event::Special("\x1B[19~"); // NOLINT -const Event Event::F9 = Event::Special("\x1B[20~"); // NOLINT -const Event Event::F10 = Event::Special("\x1B[21~"); // NOLINT -const Event Event::F11 = Event::Special("\x1B[21~"); // Doesn't exist // NOLINT + +// See https://invisible-island.net/xterm/xterm-function-keys.html +// We follow xterm-new / vterm-xf86-v4 / mgt / screen +const Event Event::F1 = Event::Special("\x1BOP"); // NOLINT +const Event Event::F2 = Event::Special("\x1BOQ"); // NOLINT +const Event Event::F3 = Event::Special("\x1BOR"); // NOLINT +const Event Event::F4 = Event::Special("\x1BOS"); // NOLINT +const Event Event::F5 = Event::Special("\x1B[15~"); // NOLINT +const Event Event::F6 = Event::Special("\x1B[17~"); // NOLINT +const Event Event::F7 = Event::Special("\x1B[18~"); // NOLINT +const Event Event::F8 = Event::Special("\x1B[19~"); // NOLINT +const Event Event::F9 = Event::Special("\x1B[20~"); // NOLINT +const Event Event::F10 = Event::Special("\x1B[21~"); // NOLINT +const Event Event::F11 = Event::Special("\x1B[23~"); // NOLINT const Event Event::F12 = Event::Special("\x1B[24~"); // NOLINT + const Event Event::Home = Event::Special({27, 91, 72}); // NOLINT const Event Event::End = Event::Special({27, 91, 70}); // NOLINT const Event Event::PageUp = Event::Special({27, 91, 53, 126}); // NOLINT diff --git a/src/ftxui/component/input.cpp b/src/ftxui/component/input.cpp index b2e4ad9..d56ce4b 100644 --- a/src/ftxui/component/input.cpp +++ b/src/ftxui/component/input.cpp @@ -48,7 +48,7 @@ bool IsWordCharacter(WordBreakProperty property) { case WordBreakProperty::Regional_Indicator: case WordBreakProperty::ZWJ: return false; - }; + } return true; // NOT_REACHED(); } diff --git a/src/ftxui/component/terminal_input_parser.cpp b/src/ftxui/component/terminal_input_parser.cpp index 0f0a036..d3f2d6a 100644 --- a/src/ftxui/component/terminal_input_parser.cpp +++ b/src/ftxui/component/terminal_input_parser.cpp @@ -3,14 +3,24 @@ #include // for uint32_t #include // for Mouse, Mouse::Button, Mouse::Motion #include // for SenderImpl, Sender -#include // for unique_ptr, allocator -#include // for move +#include +#include // for unique_ptr, allocator +#include // for move #include "ftxui/component/event.hpp" // for Event #include "ftxui/component/task.hpp" // for Task namespace ftxui { +// NOLINTNEXTLINE +const std::map g_uniformize = {{ + // Microsoft's terminal uses a different new line character for the return + // key. This also happens with linux with the `bind` command: + // See https://github.com/ArthurSonzogni/FTXUI/issues/337 + // Here, we uniformize the new line character to `\n`. + {"\r", "\n"}, +}}; + TerminalInputParser::TerminalInputParser(Sender out) : out_(std::move(out)) {} @@ -56,17 +66,14 @@ void TerminalInputParser::Send(TerminalInputParser::Output output) { pending_.clear(); return; - case SPECIAL: - // Microsoft's terminal uses a different new line character for the return - // key. This also happens with linux with the `bind` command: - // See https://github.com/ArthurSonzogni/FTXUI/issues/337 - // Here, we uniformize the new line character to `\n`. - if (pending_ == "\r") { - out_->Send(Event::Special("\n")); - } else { - out_->Send(Event::Special(std::move(pending_))); + case SPECIAL: { + auto it = g_uniformize.find(pending_); + if (it != g_uniformize.end()) { + pending_ = it->second; } + out_->Send(Event::Special(std::move(pending_))); pending_.clear(); + } return; case MOUSE: diff --git a/src/ftxui/component/terminal_input_parser_test.cpp b/src/ftxui/component/terminal_input_parser_test.cpp index 24f611d..922ee19 100644 --- a/src/ftxui/component/terminal_input_parser_test.cpp +++ b/src/ftxui/component/terminal_input_parser_test.cpp @@ -347,17 +347,17 @@ TEST(Event, Special) { {{10}, Event::Return}, {{9}, Event::Tab}, {{27, 91, 90}, Event::TabReverse}, - //{str("\x1B[OP"), Event::F1}, - //{str("\x1B[OQ"), Event::F2}, - //{str("\x1B[OR"), Event::F3}, - //{str("\x1B[OS"), Event::F4}, + {str("\x1BOP"), Event::F1}, + {str("\x1BOQ"), Event::F2}, + {str("\x1BOR"), Event::F3}, + {str("\x1BOS"), Event::F4}, {str("\x1B[15~"), Event::F5}, {str("\x1B[17~"), Event::F6}, {str("\x1B[18~"), Event::F7}, {str("\x1B[19~"), Event::F8}, {str("\x1B[20~"), Event::F9}, {str("\x1B[21~"), Event::F10}, - {str("\x1B[21~"), Event::F11}, + {str("\x1B[23~"), Event::F11}, {str("\x1B[24~"), Event::F12}, {{27, 91, 72}, Event::Home}, {{27, 91, 70}, Event::End},