vis
a vi-like editor based on Plan 9's structural regular expressions
git clone https://9o.is/git/vis.git
keys.c
(4186B)
1 #include <stdio.h>
2 #include <stdarg.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <termkey.h>
7
8 /* is c the start of a utf8 sequence? */
9 #define ISUTF8(c) (((c)&0xC0)!=0x80)
10
11 static TermKey *termkey;
12
13 static void die(const char *errstr, ...) {
14 va_list ap;
15 va_start(ap, errstr);
16 vfprintf(stderr, errstr, ap);
17 va_end(ap);
18 exit(EXIT_FAILURE);
19 }
20
21 static void print(const char *fmt, ...) {
22 va_list ap;
23 va_start(ap, fmt);
24 vfprintf(stdout, fmt, ap);
25 fflush(stdout);
26 va_end(ap);
27 }
28
29 static void delay(void) {
30 usleep(termkey_get_waittime(termkey)*10000);
31 }
32
33 static void printkey(TermKeyKey *key) {
34 switch (key->type) {
35 case TERMKEY_TYPE_UNICODE:
36 if (key->modifiers & TERMKEY_KEYMOD_SHIFT)
37 ;
38 if (key->modifiers & TERMKEY_KEYMOD_CTRL)
39 key->utf8[0] &= 0x1f;
40 if (key->modifiers & TERMKEY_KEYMOD_ALT)
41 ;
42 print("%s", key->utf8);
43 break;
44 case TERMKEY_TYPE_KEYSYM:
45 switch (key->code.sym) {
46 case TERMKEY_SYM_UNKNOWN:
47 case TERMKEY_SYM_NONE:
48 die("Unknown key sym\n");
49 case TERMKEY_SYM_BACKSPACE:
50 print("\b");
51 break;
52 case TERMKEY_SYM_TAB:
53 if (key->modifiers & TERMKEY_KEYMOD_SHIFT)
54 print("\033[Z");
55 else
56 print("\t");
57 break;
58 case TERMKEY_SYM_ENTER:
59 print("\n");
60 break;
61 case TERMKEY_SYM_ESCAPE:
62 print("\033");
63 delay();
64 break;
65 case TERMKEY_SYM_SPACE:
66 print(" ");
67 break;
68 case TERMKEY_SYM_UP:
69 print("\033OA");
70 break;
71 case TERMKEY_SYM_DOWN:
72 print("\033OB");
73 break;
74 case TERMKEY_SYM_RIGHT:
75 print("\033OC");
76 break;
77 case TERMKEY_SYM_LEFT:
78 print("\033OD");
79 break;
80 case TERMKEY_SYM_DEL:
81 case TERMKEY_SYM_BEGIN:
82 case TERMKEY_SYM_FIND:
83 case TERMKEY_SYM_INSERT:
84 case TERMKEY_SYM_DELETE:
85 case TERMKEY_SYM_SELECT:
86 case TERMKEY_SYM_PAGEUP:
87 case TERMKEY_SYM_PAGEDOWN:
88 case TERMKEY_SYM_HOME:
89 case TERMKEY_SYM_END:
90 case TERMKEY_SYM_CANCEL:
91 case TERMKEY_SYM_CLEAR:
92 case TERMKEY_SYM_CLOSE:
93 case TERMKEY_SYM_COMMAND:
94 case TERMKEY_SYM_COPY:
95 case TERMKEY_SYM_EXIT:
96 case TERMKEY_SYM_HELP:
97 case TERMKEY_SYM_MARK:
98 case TERMKEY_SYM_MESSAGE:
99 case TERMKEY_SYM_MOVE:
100 case TERMKEY_SYM_OPEN:
101 case TERMKEY_SYM_OPTIONS:
102 case TERMKEY_SYM_PRINT:
103 case TERMKEY_SYM_REDO:
104 case TERMKEY_SYM_REFERENCE:
105 case TERMKEY_SYM_REFRESH:
106 case TERMKEY_SYM_REPLACE:
107 case TERMKEY_SYM_RESTART:
108 case TERMKEY_SYM_RESUME:
109 case TERMKEY_SYM_SAVE:
110 case TERMKEY_SYM_SUSPEND:
111 case TERMKEY_SYM_UNDO:
112 case TERMKEY_SYM_KP0:
113 case TERMKEY_SYM_KP1:
114 case TERMKEY_SYM_KP2:
115 case TERMKEY_SYM_KP3:
116 case TERMKEY_SYM_KP4:
117 case TERMKEY_SYM_KP5:
118 case TERMKEY_SYM_KP6:
119 case TERMKEY_SYM_KP7:
120 case TERMKEY_SYM_KP8:
121 case TERMKEY_SYM_KP9:
122 case TERMKEY_SYM_KPENTER:
123 case TERMKEY_SYM_KPPLUS:
124 case TERMKEY_SYM_KPMINUS:
125 case TERMKEY_SYM_KPMULT:
126 case TERMKEY_SYM_KPDIV:
127 case TERMKEY_SYM_KPCOMMA:
128 case TERMKEY_SYM_KPPERIOD:
129 case TERMKEY_SYM_KPEQUALS:
130 default:
131 break;
132 }
133 break;
134 case TERMKEY_TYPE_FUNCTION:
135 case TERMKEY_TYPE_MOUSE:
136 case TERMKEY_TYPE_POSITION:
137 case TERMKEY_TYPE_MODEREPORT:
138 case TERMKEY_TYPE_UNKNOWN_CSI:
139 default:
140 break;
141 }
142 }
143
144 int main(int argc, char *argv[]) {
145 char buf[1024];
146 FILE *file = stdin;
147 char *term = getenv("TERM");
148 if (!term)
149 term = "xterm";
150 if (!(termkey = termkey_new_abstract(term, TERMKEY_FLAG_UTF8)))
151 die("Failed to initialize libtermkey\n");
152 while (fgets(buf, sizeof buf, file)) {
153 const char *keys = buf, *next;
154 while (*keys) {
155 TermKeyKey key = { 0 };
156 if (*keys == '\n') {
157 keys++;
158 } else if (*keys == '<' && (next = termkey_strpkey(termkey, keys+1, &key, TERMKEY_FORMAT_VIM)) && *next == '>') {
159 printkey(&key);
160 keys = next+1;
161 } else {
162 const char *start = keys;
163 if (ISUTF8(*keys))
164 keys++;
165 while (!ISUTF8(*keys))
166 keys++;
167 size_t len = keys - start;
168 if (len >= sizeof(key.utf8))
169 die("Too long UTF-8 sequence: %s\n", start);
170 // FIXME: not really correct, bug good enough for now
171 key.type = TERMKEY_TYPE_UNICODE;
172 key.modifiers = 0;
173 if (len > 0)
174 memcpy(key.utf8, start, len);
175 key.utf8[len] = '\0';
176 printkey(&key);
177 }
178 }
179 }
180
181 return 0;
182 }