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 }