diff options
author | Nico Weber <thakis@chromium.org> | 2020-09-13 20:33:04 -0400 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-09-15 09:45:13 +0200 |
commit | 2fe127d96ff9991d13d73e4c26c85cb44efeac99 (patch) | |
tree | b89375eae56ad18525a098e0f94aee4f779f7930 /Libraries/LibLine | |
parent | 365fa05a8256d1ba44cff5d05c44dda5021571e9 (diff) | |
download | serenity-2fe127d96ff9991d13d73e4c26c85cb44efeac99.zip |
LibLine: Parse CSI parameters and immediates
No behavior change, but it makes it easy to handle
page up and page down if we wanted to make them do something
in libline.
Diffstat (limited to 'Libraries/LibLine')
-rw-r--r-- | Libraries/LibLine/Editor.cpp | 69 | ||||
-rw-r--r-- | Libraries/LibLine/Editor.h | 5 |
2 files changed, 52 insertions, 22 deletions
diff --git a/Libraries/LibLine/Editor.cpp b/Libraries/LibLine/Editor.cpp index 08bef585fa..9a2e271224 100644 --- a/Libraries/LibLine/Editor.cpp +++ b/Libraries/LibLine/Editor.cpp @@ -631,6 +631,11 @@ void Editor::handle_read_event() Utf8View input_view { StringView { m_incomplete_data.data(), valid_bytes } }; size_t consumed_code_points = 0; + Vector<u8, 4> csi_parameter_bytes; + Vector<unsigned, 4> csi_parameters; + Vector<u8> csi_intermediate_bytes; + u8 csi_final; + for (auto code_point : input_view) { if (m_finish) break; @@ -644,7 +649,7 @@ void Editor::handle_read_event() case InputState::GotEscape: switch (code_point) { case '[': - m_state = InputState::GotEscapeFollowedByLeftBracket; + m_state = InputState::CSIExpectParameter; continue; default: { m_state = InputState::Free; @@ -658,29 +663,55 @@ void Editor::handle_read_event() continue; } } - case InputState::GotEscapeFollowedByLeftBracket: - if (code_point == 'O') { + case InputState::CSIExpectParameter: + if (code_point >= 0x30 && code_point <= 0x3f) { // '0123456789:;<=>?' + csi_parameter_bytes.append(code_point); + continue; + } + m_state = InputState::CSIExpectIntermediate; + [[fallthrough]]; + case InputState::CSIExpectIntermediate: + if (code_point >= 0x20 && code_point <= 0x2f) { // ' !"#$%&\'()*+,-./' + csi_intermediate_bytes.append(code_point); + continue; + } + m_state = InputState::CSIExpectFinal; + [[fallthrough]]; + case InputState::CSIExpectFinal: + m_state = InputState::Free; + if (!(code_point >= 0x40 && code_point <= 0x7f)) { + dbgprintf("LibLine: Invalid CSI: %02x (%c)\r\n", code_point, code_point); + ctrl_held = false; + continue; + } + csi_final = code_point; + + for (auto& parameter : String::copy(csi_parameter_bytes).split(';')) { + if (auto value = parameter.to_uint(); value.has_value()) + csi_parameters.append(value.value()); + else + csi_parameters.append(0); + } + + if (csi_final == 'O') { // mod_ctrl ctrl_held = true; continue; } - if (code_point == 'Z') { + if (csi_final == 'Z') { // 'reverse tab' reverse_tab = true; - m_state = InputState::Free; ctrl_held = false; break; } cleanup_suggestions(); - switch (code_point) { + switch (csi_final) { case 'A': // ^[[A: arrow up search_backwards(); - m_state = InputState::Free; ctrl_held = false; continue; case 'B': // ^[[B: arrow down search_forwards(); - m_state = InputState::Free; ctrl_held = false; continue; case 'D': // ^[[D: arrow left @@ -688,7 +719,6 @@ void Editor::handle_read_event() cursor_left_word(); else cursor_left_character(); - m_state = InputState::Free; ctrl_held = false; continue; case 'C': // ^[[C: arrow right @@ -696,35 +726,34 @@ void Editor::handle_read_event() cursor_right_word(); else cursor_right_character(); - m_state = InputState::Free; ctrl_held = false; continue; case 'H': // ^[[H: home go_home(); - m_state = InputState::Free; ctrl_held = false; continue; case 'F': // ^[[F: end go_end(); - m_state = InputState::Free; ctrl_held = false; continue; - case '3': // ^[[3~: delete - erase_character_forwards(); - m_search_offset = 0; - m_state = InputState::ExpectTerminator; + case '~': + if (csi_parameters.size() == 1 && csi_parameters[0] == 3) { // ^[[3~: delete + erase_character_forwards(); + m_search_offset = 0; + ctrl_held = false; + continue; + } + // ^[[5~: page up + // ^[[6~: page down + dbgprintf("LibLine: Unhandled '~'\r\n"); ctrl_held = false; continue; default: dbgprintf("LibLine: Unhandled final: %02x (%c)\r\n", code_point, code_point); - m_state = InputState::Free; ctrl_held = false; continue; } break; - case InputState::ExpectTerminator: - m_state = InputState::Free; - continue; case InputState::Free: if (code_point == 27) { m_state = InputState::GotEscape; diff --git a/Libraries/LibLine/Editor.h b/Libraries/LibLine/Editor.h index bf026b62b7..fe32d5bfba 100644 --- a/Libraries/LibLine/Editor.h +++ b/Libraries/LibLine/Editor.h @@ -471,8 +471,9 @@ private: enum class InputState { Free, GotEscape, - GotEscapeFollowedByLeftBracket, - ExpectTerminator, + CSIExpectParameter, + CSIExpectIntermediate, + CSIExpectFinal, }; InputState m_state { InputState::Free }; |