/src/serenity/Userland/Libraries/LibLine/KeyCallbackMachine.cpp
Line | Count | Source |
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 | | |
10 | | namespace Line { |
11 | | |
12 | | void KeyCallbackMachine::register_key_input_callback(Vector<Key> keys, Function<bool(Editor&)> callback) |
13 | 0 | { |
14 | 0 | m_key_callbacks.set(keys, make<KeyCallback>(move(callback))); |
15 | 0 | } |
16 | | |
17 | | void KeyCallbackMachine::key_pressed(Editor& editor, Key key) |
18 | 0 | { |
19 | 0 | 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()); |
20 | 0 | if (m_sequence_length == 0) { |
21 | 0 | VERIFY(m_current_matching_keys.is_empty()); |
22 | | |
23 | 0 | for (auto& it : m_key_callbacks) { |
24 | 0 | if (it.key.first() == key) |
25 | 0 | m_current_matching_keys.append(it.key); |
26 | 0 | } |
27 | |
|
28 | 0 | if (m_current_matching_keys.is_empty()) { |
29 | 0 | m_should_process_this_key = true; |
30 | 0 | return; |
31 | 0 | } |
32 | 0 | } |
33 | | |
34 | 0 | ++m_sequence_length; |
35 | 0 | Vector<Vector<Key>> old_matching_keys; |
36 | 0 | swap(m_current_matching_keys, old_matching_keys); |
37 | |
|
38 | 0 | for (auto& okey : old_matching_keys) { |
39 | 0 | if (okey.size() < m_sequence_length) |
40 | 0 | continue; |
41 | | |
42 | 0 | if (okey[m_sequence_length - 1] == key) |
43 | 0 | m_current_matching_keys.append(okey); |
44 | 0 | } |
45 | |
|
46 | 0 | if (m_current_matching_keys.is_empty()) { |
47 | | // Insert any keys that were captured |
48 | 0 | if (!old_matching_keys.is_empty()) { |
49 | 0 | auto& keys = old_matching_keys.first(); |
50 | 0 | for (size_t i = 0; i < m_sequence_length - 1; ++i) |
51 | 0 | editor.insert(keys[i].key); |
52 | 0 | } |
53 | 0 | m_sequence_length = 0; |
54 | 0 | m_should_process_this_key = true; |
55 | 0 | return; |
56 | 0 | } |
57 | | |
58 | | if constexpr (CALLBACK_MACHINE_DEBUG) { |
59 | | dbgln("seq_length={}, matching vector:", m_sequence_length); |
60 | | for (auto& key : m_current_matching_keys) { |
61 | | for (auto& k : key) |
62 | | dbgln(" {}, {}", k.key, k.modifiers); |
63 | | dbgln(""); |
64 | | } |
65 | | } |
66 | |
|
67 | 0 | m_should_process_this_key = false; |
68 | 0 | for (auto& key : m_current_matching_keys) { |
69 | 0 | if (key.size() == m_sequence_length) { |
70 | 0 | m_should_process_this_key = m_key_callbacks.get(key).value()->callback(editor); |
71 | 0 | m_sequence_length = 0; |
72 | 0 | m_current_matching_keys.clear(); |
73 | 0 | return; |
74 | 0 | } |
75 | 0 | } |
76 | 0 | } |
77 | | |
78 | | void KeyCallbackMachine::interrupted(Editor& editor) |
79 | 0 | { |
80 | 0 | m_sequence_length = 0; |
81 | 0 | m_current_matching_keys.clear(); |
82 | 0 | if (auto callback = m_key_callbacks.get({ ctrl('C') }); callback.has_value()) |
83 | 0 | m_should_process_this_key = callback.value()->callback(editor); |
84 | 0 | else |
85 | 0 | m_should_process_this_key = true; |
86 | 0 | } |
87 | | |
88 | | } |