summaryrefslogtreecommitdiff
path: root/config.cpp
blob: 77e3ed5c9d438d6ebb3749ab68438c71525adf27 (plain)
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
#include <cassert>
#include <termio.h>

#include "command.h"
#include "config.h"
#include "throw.h"

using namespace std;


KeyInputMachine global_keyinput({
	{{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_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;
}