1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
#include <cassert>
#include <termio.h>
#include "command.h"
#include "config.h"
#include "throw.h"
using namespace std;
KeyInputMachine global_keyinput({
{{KEY_CTRL+'Q',KEY_CTRL+'Q'},{"quit_app"}},
{{KEY_ALT+';'},{"display_prompt"}},
{{KEY_CTRL+'S'},{"save_file"}},
{{KEY_CTRL+'O'},{"open_prompt"}},
{{KEY_CTRL+'W'},{"close_tab"}},
{{KEY_ALT+'\t'},{"cycle_tabs"}},
{{KEY_ALT+KEY_SHIFTTAB},{"cycle_tabs_back"}},
{{KEY_ESC},{"cancel"}},
{{'\n'},{"insert_newline"}},
{{'\t'},{"insert_char","\t"}},
{{KEY_BACKSPACE},{"delete_backward"}},
{{KEY_DELETE},{"delete_forward"}},
{{KEY_RIGHT},{"move_forward"}},
{{KEY_LEFT},{"move_backward"}},
{{KEY_DOWN},{"move_downward"}},
{{KEY_UP},{"move_upward"}},
{{KEY_PAGEDOWN},{"move_pagedown"}},
{{KEY_PAGEUP},{"move_pageup"}},
});
class Init{public: Init(){
for(int i=32;i<127;i++){
global_keyinput.insert({i},Command("insert_char",string(1,(char)i)));
}
}} init_object;
KeyInputMachine::TreeNode::~TreeNode(){
if(cmd)delete cmd;
if(m){
for(const pair<int,TreeNode*> &p : *m){
if(p.second!=nullptr)delete p.second;
}
}
}
KeyInputMachine::KeyInputMachine(){}
KeyInputMachine::KeyInputMachine(const vector<pair<vector<int>,Command>> &list){
for(const pair<vector<int>,Command> &p : list){
insert(p.first,p.second);
}
}
void KeyInputMachine::insert(const vector<int> &keys,const Command &cmd){
assert(keys.size()>0);
TreeNode *node=&root;
for(int key : keys){
if(node->m==nullptr){
if(node->cmd){
THROW("Ambiguous keybinding!");
}
node->m=new unordered_map<int,TreeNode*>;
}
TreeNode *newnode=new TreeNode;
(*node->m)[key]=newnode;
node=newnode;
}
if(node->cmd!=nullptr)delete node->cmd;
node->cmd=new Command(cmd);
}
Either<bool,Command> KeyInputMachine::input(int key){
if(current->m==nullptr){
current=&root;
return {Left(),false};
}
auto it=current->m->find(key);
if(it==current->m->end()){
current=&root;
return {Left(),false};
}
current=it->second;
if(current->cmd!=nullptr){
Command *cmd=current->cmd;
current=&root;
return {Right(),*cmd};
} else {
return {Left(),true};
}
}
void KeyInputMachine::cancel(){
current=&root;
}
|