From 6215240b3722743b6e120b0734faaa8d538e0167 Mon Sep 17 00:00:00 2001
From: Arthur Sonzogni <sonzogniarthur@gmail.com>
Date: Tue, 25 Apr 2023 08:52:16 +0200
Subject: [PATCH] Support arrow keys in application mode. (#627)

Depending on the Cursor Key Mode (DECCKM), the terminal sends different
escape sequences:

Key     Normal    Application
-----   --------  -----------
Up      ESC [ A   ESC O A
Down    ESC [ B   ESC O B
Right   ESC [ C   ESC O C
Left    ESC [ D   ESC O D
Home    ESC [ H   ESC O H
End     ESC [ F   ESC O F

I decided not to update the current mode to fit what FTXUI parse, but
instead support parsing both. We convert the sequences from the
"application mode" into the "normal mode".

Bug:https://github.com/ArthurSonzogni/FTXUI/issues/626
Fixed:https://github.com/ArthurSonzogni/FTXUI/issues/626
---
 src/ftxui/component/terminal_input_parser.cpp | 23 +++++++++++
 .../component/terminal_input_parser_test.cpp  | 40 +++++++++++++++----
 2 files changed, 55 insertions(+), 8 deletions(-)

diff --git a/src/ftxui/component/terminal_input_parser.cpp b/src/ftxui/component/terminal_input_parser.cpp
index a77d843d..72da0d16 100644
--- a/src/ftxui/component/terminal_input_parser.cpp
+++ b/src/ftxui/component/terminal_input_parser.cpp
@@ -19,8 +19,31 @@ const std::map<std::string, std::string> g_uniformize = {
     // See https://github.com/ArthurSonzogni/FTXUI/issues/337
     // Here, we uniformize the new line character to `\n`.
     {"\r", "\n"},
+
     // See: https://github.com/ArthurSonzogni/FTXUI/issues/508
     {std::string({8}), std::string({127})},
+
+    // See: https://github.com/ArthurSonzogni/FTXUI/issues/626
+    //
+    // Depending on the Cursor Key Mode (DECCKM), the terminal sends different
+    // escape sequences:
+    //
+    //   Key     Normal    Application
+    //   -----   --------  -----------
+    //   Up      ESC [ A   ESC O A
+    //   Down    ESC [ B   ESC O B
+    //   Right   ESC [ C   ESC O C
+    //   Left    ESC [ D   ESC O D
+    //   Home    ESC [ H   ESC O H
+    //   End     ESC [ F   ESC O F
+    //
+    {"\x1BOA", "\x1B[A"}, // UP
+    {"\x1BOB", "\x1B[B"}, // DOWN
+    {"\x1BOC", "\x1B[C"}, // RIGHT
+    {"\x1BOD", "\x1B[D"}, // LEFT
+    {"\x1BOH", "\x1B[H"}, // HOME
+    {"\x1BOF", "\x1B[F"}, // END
+
 };
 
 TerminalInputParser::TerminalInputParser(Sender<Task> out)
diff --git a/src/ftxui/component/terminal_input_parser_test.cpp b/src/ftxui/component/terminal_input_parser_test.cpp
index 4acf84d3..4eec23b4 100644
--- a/src/ftxui/component/terminal_input_parser_test.cpp
+++ b/src/ftxui/component/terminal_input_parser_test.cpp
@@ -334,22 +334,44 @@ TEST(Event, Special) {
       output.push_back(it);
     return output;
   };
+
   struct {
     std::vector<unsigned char> input;
     Event expected;
   } kTestCase[] = {
-      {str("\x1B[D"), Event::ArrowLeft},
-      {str("\x1B[C"), Event::ArrowRight},
+      // Arrow (defaut cursor mode)
       {str("\x1B[A"), Event::ArrowUp},
       {str("\x1B[B"), Event::ArrowDown},
+      {str("\x1B[C"), Event::ArrowRight},
+      {str("\x1B[D"), Event::ArrowLeft},
+      {str("\x1B[H"), Event::Home},
+      {str("\x1B[F"), Event::End},
+
+      // Arrow (application cursor mode)
+      {str("\x1BOA"), Event::ArrowUp},
+      {str("\x1BOB"), Event::ArrowDown},
+      {str("\x1BOC"), Event::ArrowRight},
+      {str("\x1BOD"), Event::ArrowLeft},
+      {str("\x1BOH"), Event::Home},
+      {str("\x1BOF"), Event::End},
+
+      // Backspace & Quirk for:
+      // https://github.com/ArthurSonzogni/FTXUI/issues/508
       {{127}, Event::Backspace},
-      // Quirk for: https://github.com/ArthurSonzogni/FTXUI/issues/508
       {{8}, Event::Backspace},
+
+      // Delete
       {str("\x1B[3~"), Event::Delete},
-      //{str("\x1B"), Event::Escape},
+
+      // Return
+      {{13}, Event::Return},
       {{10}, Event::Return},
+
+      // Tabs:
       {{9}, Event::Tab},
       {{27, 91, 90}, Event::TabReverse},
+
+      // Function keys
       {str("\x1BOP"), Event::F1},
       {str("\x1BOQ"), Event::F2},
       {str("\x1BOR"), Event::F3},
@@ -362,10 +384,12 @@ TEST(Event, Special) {
       {str("\x1B[21~"), Event::F10},
       {str("\x1B[23~"), Event::F11},
       {str("\x1B[24~"), Event::F12},
-      {{27, 91, 72}, Event::Home},
-      {{27, 91, 70}, Event::End},
-      {{27, 91, 53, 126}, Event::PageUp},
-      {{27, 91, 54, 126}, Event::PageDown},
+
+      // Page up and down:
+      {str("\x1B[5~"), Event::PageUp},
+      {str("\x1B[6~"), Event::PageDown},
+
+      // Custom:
       {{0}, Event::Custom},
   };
 
-- 
GitLab