-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkey_state_machine.cpp
More file actions
129 lines (107 loc) · 2.2 KB
/
key_state_machine.cpp
File metadata and controls
129 lines (107 loc) · 2.2 KB
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
/*
*
* Command handler for maping characters from stdin to command
* handler. Use lnAddKeyHandler() to build the tree of key sequences
* that map to function calls.
*
* Example: to call the forward_char function for the escape sequence
*
*
* Copyright (c) 2015, Wing Eng
* All rights reserved.
*/
#include <deque>
#include <unistd.h>
#include <assert.h>
#include "linenoise.h"
#include "linenoise_private.h"
using namespace std;
class key_node_c {
public:
key_node_c (int ch) : kn_ch(ch) {};
public:
int kn_ch;
cmd_func kn_func;
vector<key_node_c *> kn_children;
};
typedef vector<key_node_c *> cmd_vec_t;
static cmd_vec_t cmd_map;
static deque<char> char_stack;
static key_node_c *
find_key_node (cmd_vec_t &cmd_map, int ch, int match_any = 1)
{
for (auto kn : cmd_map) {
if (kn->kn_ch == ch)
return kn;
if (kn->kn_ch == '*' && match_any)
return kn;
}
return NULL;
}
static void
nextChar (int fd, char &c)
{
if (char_stack.size()) {
c = char_stack.front();
char_stack.pop_front();
return;
}
if (read(fd, &c, 1) != 1) {
assert(0);
}
}
/*
* Push a char back into the read loop, use this char instead
* of stdin, used for complete line where the char wasn't consumed
*/
void
lnPushChar (char c)
{
char_stack.push_back(c);
}
static key_node_c *
lnGetKeys (cmd_vec_t &cmd_map, int fd, char &ch)
{
nextChar(fd, ch);
auto kn = find_key_node(cmd_map, ch);
if (kn) {
if (kn->kn_children.size()) {
return lnGetKeys(kn->kn_children, fd, ch);
} else {
if (kn->kn_func)
return kn;
}
}
return NULL;
}
static void
addKeyHandler (cmd_vec_t &cmap, const char *seq, cmd_func func)
{
key_node_c *kn;
if ((kn = find_key_node(cmap, *seq, 0)) == NULL) {
kn = new key_node_c(*seq);
cmap.push_back(kn);
}
kn->kn_func = func;
if (seq[1] == '\0')
return;
addKeyHandler(kn->kn_children, seq + 1, func);
}
void
lnAddKeyHandler (const char *seq, cmd_func func)
{
addKeyHandler(cmd_map, seq, func);
}
int
lnHandleKeys (int fd, int *done)
{
char ch;
int ret = 00;
while (!*done) {
auto kn = lnGetKeys(cmd_map, fd, ch);
if (kn && kn->kn_func) {
ret = kn->kn_func(ch);
}
}
return ret;
}