Serenity Operating System
at master 92 lines 2.7 kB view raw
1/* 2 * Copyright (c) 2020, the SerenityOS developers. 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#include <AK/Debug.h> 8#include <LibLine/Editor.h> 9 10namespace { 11constexpr u32 ctrl(char c) { return c & 0x3f; } 12} 13 14namespace Line { 15 16void KeyCallbackMachine::register_key_input_callback(Vector<Key> keys, Function<bool(Editor&)> callback) 17{ 18 m_key_callbacks.set(keys, make<KeyCallback>(move(callback))); 19} 20 21void KeyCallbackMachine::key_pressed(Editor& editor, Key key) 22{ 23 dbgln_if(CALLBACK_MACHINE_DEBUG, "Key<{}, {}> pressed, seq_length={}, {} things in the matching vector", key.key, key.modifiers, m_sequence_length, m_current_matching_keys.size()); 24 if (m_sequence_length == 0) { 25 VERIFY(m_current_matching_keys.is_empty()); 26 27 for (auto& it : m_key_callbacks) { 28 if (it.key.first() == key) 29 m_current_matching_keys.append(it.key); 30 } 31 32 if (m_current_matching_keys.is_empty()) { 33 m_should_process_this_key = true; 34 return; 35 } 36 } 37 38 ++m_sequence_length; 39 Vector<Vector<Key>> old_matching_keys; 40 swap(m_current_matching_keys, old_matching_keys); 41 42 for (auto& okey : old_matching_keys) { 43 if (okey.size() < m_sequence_length) 44 continue; 45 46 if (okey[m_sequence_length - 1] == key) 47 m_current_matching_keys.append(okey); 48 } 49 50 if (m_current_matching_keys.is_empty()) { 51 // Insert any keys that were captured 52 if (!old_matching_keys.is_empty()) { 53 auto& keys = old_matching_keys.first(); 54 for (size_t i = 0; i < m_sequence_length - 1; ++i) 55 editor.insert(keys[i].key); 56 } 57 m_sequence_length = 0; 58 m_should_process_this_key = true; 59 return; 60 } 61 62 if constexpr (CALLBACK_MACHINE_DEBUG) { 63 dbgln("seq_length={}, matching vector:", m_sequence_length); 64 for (auto& key : m_current_matching_keys) { 65 for (auto& k : key) 66 dbgln(" {}, {}", k.key, k.modifiers); 67 dbgln(""); 68 } 69 } 70 71 m_should_process_this_key = false; 72 for (auto& key : m_current_matching_keys) { 73 if (key.size() == m_sequence_length) { 74 m_should_process_this_key = m_key_callbacks.get(key).value()->callback(editor); 75 m_sequence_length = 0; 76 m_current_matching_keys.clear(); 77 return; 78 } 79 } 80} 81 82void KeyCallbackMachine::interrupted(Editor& editor) 83{ 84 m_sequence_length = 0; 85 m_current_matching_keys.clear(); 86 if (auto callback = m_key_callbacks.get({ ctrl('C') }); callback.has_value()) 87 m_should_process_this_key = callback.value()->callback(editor); 88 else 89 m_should_process_this_key = true; 90} 91 92}