edit: Split escape code parsing into a separate function

This makes edit_read_char() simpler and easier to extend since it
does not need to know anything about the escape codes anymore.
This commit is contained in:
Jouni Malinen 2010-11-20 15:55:51 +02:00
parent 0954399c90
commit 0bee81352f

View file

@ -251,12 +251,6 @@ static void history_debug_dump(void)
static void insert_char(int c) static void insert_char(int c)
{ {
if (c < 32 && c > 255) {
printf("[%d]\n", c);
edit_redraw();
return;
}
if (cmdbuf_len >= (int) sizeof(cmdbuf) - 1) if (cmdbuf_len >= (int) sizeof(cmdbuf) - 1)
return; return;
if (cmdbuf_len == cmdbuf_pos) { if (cmdbuf_len == cmdbuf_pos) {
@ -417,158 +411,328 @@ static void complete(int list)
} }
static void edit_read_char(int sock, void *eloop_ctx, void *sock_ctx) enum edit_key_code {
EDIT_KEY_NONE = 256,
EDIT_KEY_TAB,
EDIT_KEY_UP,
EDIT_KEY_DOWN,
EDIT_KEY_RIGHT,
EDIT_KEY_LEFT,
EDIT_KEY_ENTER,
EDIT_KEY_BACKSPACE,
EDIT_KEY_INSERT,
EDIT_KEY_DELETE,
EDIT_KEY_HOME,
EDIT_KEY_END,
EDIT_KEY_PAGE_UP,
EDIT_KEY_PAGE_DOWN,
EDIT_KEY_F1,
EDIT_KEY_F2,
EDIT_KEY_F3,
EDIT_KEY_F4,
EDIT_KEY_F5,
EDIT_KEY_F6,
EDIT_KEY_F7,
EDIT_KEY_F8,
EDIT_KEY_F9,
EDIT_KEY_F10,
EDIT_KEY_F11,
EDIT_KEY_F12,
EDIT_KEY_CTRL_UP,
EDIT_KEY_CTRL_DOWN,
EDIT_KEY_CTRL_RIGHT,
EDIT_KEY_CTRL_LEFT,
EDIT_KEY_CTRL_A,
EDIT_KEY_CTRL_B,
EDIT_KEY_CTRL_D,
EDIT_KEY_CTRL_E,
EDIT_KEY_CTRL_F,
EDIT_KEY_CTRL_G,
EDIT_KEY_CTRL_H,
EDIT_KEY_CTRL_J,
EDIT_KEY_CTRL_K,
EDIT_KEY_CTRL_L,
EDIT_KEY_CTRL_N,
EDIT_KEY_CTRL_O,
EDIT_KEY_CTRL_P,
EDIT_KEY_CTRL_R,
EDIT_KEY_CTRL_T,
EDIT_KEY_CTRL_U,
EDIT_KEY_CTRL_V,
EDIT_KEY_CTRL_W,
EDIT_KEY_ALT_UP,
EDIT_KEY_ALT_DOWN,
EDIT_KEY_ALT_RIGHT,
EDIT_KEY_ALT_LEFT,
EDIT_KEY_EOF
};
static void show_esc_buf(const char *esc_buf, char c, int i)
{
edit_clear_line();
printf("\rESC buffer '%s' c='%c' [%d]\n", esc_buf, c, i);
edit_redraw();
}
static enum edit_key_code edit_read_key(int sock)
{ {
int c; int c;
unsigned char buf[1]; unsigned char buf[1];
int res; int res;
static int esc = -1; static int esc = -1;
static char esc_buf[6]; static char esc_buf[6];
static int last_tab = 0;
res = read(sock, buf, 1); res = read(sock, buf, 1);
if (res < 0) if (res < 0)
perror("read"); perror("read");
if (res <= 0) { if (res <= 0)
edit_eof_cb(edit_cb_ctx); return EDIT_KEY_EOF;
return;
}
c = buf[0]; c = buf[0];
if (c != 9)
last_tab = 0;
if (esc >= 0) { if (esc >= 0) {
if (esc == 5) { if (esc == 5) {
printf("{ESC%s}[0]\n", esc_buf); show_esc_buf(esc_buf, c, 0);
edit_redraw();
esc = -1; esc = -1;
} else { } else {
esc_buf[esc++] = c; esc_buf[esc++] = c;
esc_buf[esc] = '\0'; esc_buf[esc] = '\0';
if (esc == 1) if (esc == 1)
return; return EDIT_KEY_NONE;
} }
} }
if (esc == 2 && esc_buf[0] == '[' && c >= 'A' && c <= 'Z') { if (esc == 2 && esc_buf[0] == '[' && c >= 'A' && c <= 'Z') {
switch (c) {
case 'A': /* up */
history_prev();
break;
case 'B': /* down */
history_next();
break;
case 'C': /* right */
move_right();
break;
case 'D': /* left */
move_left();
break;
default:
printf("{ESC%s}[1]\n", esc_buf);
edit_redraw();
break;
}
esc = -1; esc = -1;
return; switch (c) {
case 'A':
return EDIT_KEY_UP;
case 'B':
return EDIT_KEY_DOWN;
case 'C':
return EDIT_KEY_RIGHT;
case 'D':
return EDIT_KEY_LEFT;
default:
show_esc_buf(esc_buf, c, 1);
return EDIT_KEY_NONE;
}
} }
if (esc > 1 && esc_buf[0] == '[') { if (esc > 1 && esc_buf[0] == '[') {
if ((c >= '0' && c <= '9') || c == ';') if ((c >= '0' && c <= '9') || c == ';')
return; return EDIT_KEY_NONE;
esc = -1;
if (esc_buf[1] == '1' && esc_buf[2] == ';' && if (esc_buf[1] == '1' && esc_buf[2] == ';' &&
esc_buf[3] == '5') { esc_buf[3] == '5') {
switch (esc_buf[4]) { switch (esc_buf[4]) {
case 'A': /* Ctrl-Up */ case 'A':
case 'B': /* Ctrl-Down */ return EDIT_KEY_CTRL_UP;
break; case 'B':
case 'C': /* Ctrl-Right */ return EDIT_KEY_CTRL_DOWN;
move_word_right(); case 'C':
break; return EDIT_KEY_CTRL_RIGHT;
case 'D': /* Ctrl-Left */ case 'D':
move_word_left(); return EDIT_KEY_CTRL_LEFT;
break;
default: default:
printf("{ESC%s}[2]\n", esc_buf); show_esc_buf(esc_buf, c, 2);
edit_redraw(); return EDIT_KEY_NONE;
break; }
}
if (esc_buf[1] == '1' && esc_buf[2] == ';' &&
esc_buf[3] == '3') {
switch (esc_buf[4]) {
case 'A':
return EDIT_KEY_ALT_UP;
case 'B':
return EDIT_KEY_ALT_DOWN;
case 'C':
return EDIT_KEY_ALT_RIGHT;
case 'D':
return EDIT_KEY_ALT_LEFT;
default:
show_esc_buf(esc_buf, c, 7);
return EDIT_KEY_NONE;
} }
esc = -1;
return;
} }
switch (c) { switch (c) {
case '~': case '~':
switch (atoi(&esc_buf[1])) { switch (atoi(&esc_buf[1])) {
case 2: /* Insert */ case 2:
break; return EDIT_KEY_INSERT;
case 3: /* Delete */ case 3:
delete_current(); return EDIT_KEY_DELETE;
break; case 5:
case 5: /* Page Up */ return EDIT_KEY_PAGE_UP;
case 6: /* Page Down */ case 6:
case 15: /* F5 */ return EDIT_KEY_PAGE_DOWN;
case 17: /* F6 */ case 15:
case 18: /* F7 */ return EDIT_KEY_F5;
case 19: /* F8 */ case 17:
case 20: /* F9 */ return EDIT_KEY_F6;
case 21: /* F10 */ case 18:
case 23: /* F11 */ return EDIT_KEY_F7;
case 24: /* F12 */ case 19:
break; return EDIT_KEY_F8;
case 20:
return EDIT_KEY_F9;
case 21:
return EDIT_KEY_F10;
case 23:
return EDIT_KEY_F11;
case 24:
return EDIT_KEY_F12;
default: default:
printf("{ESC%s}[3]\n", esc_buf); show_esc_buf(esc_buf, c, 3);
edit_redraw(); return EDIT_KEY_NONE;
break;
} }
break; break;
default: default:
printf("{ESC%s}[4]\n", esc_buf); show_esc_buf(esc_buf, c, 4);
edit_redraw(); return EDIT_KEY_NONE;
break;
} }
esc = -1;
return;
} }
if (esc > 1 && esc_buf[0] == 'O') { if (esc > 1 && esc_buf[0] == 'O') {
switch (esc_buf[1]) {
case 'F': /* end */
move_end();
break;
case 'H': /* home */
move_start();
break;
case 'P': /* F1 */
history_debug_dump();
break;
case 'Q': /* F2 */
case 'R': /* F3 */
case 'S': /* F4 */
break;
default:
printf("{ESC%s}[5]\n", esc_buf);
edit_redraw();
break;
}
esc = -1; esc = -1;
return; switch (esc_buf[1]) {
case 'F':
return EDIT_KEY_END;
case 'H':
return EDIT_KEY_HOME;
case 'P':
return EDIT_KEY_F1;
case 'Q':
return EDIT_KEY_F2;
case 'R':
return EDIT_KEY_F3;
case 'S':
return EDIT_KEY_F4;
default:
show_esc_buf(esc_buf, c, 5);
return EDIT_KEY_NONE;
}
} }
if (esc > 1) { if (esc > 1) {
printf("{ESC%s}[6]\n", esc_buf);
edit_redraw();
esc = -1; esc = -1;
return; show_esc_buf(esc_buf, c, 6);
return EDIT_KEY_NONE;
} }
switch (c) { switch (c) {
case 1: /* ^A */ case 1:
return EDIT_KEY_CTRL_A;
case 2:
return EDIT_KEY_CTRL_B;
case 4:
return EDIT_KEY_CTRL_D;
case 5:
return EDIT_KEY_CTRL_E;
case 6:
return EDIT_KEY_CTRL_F;
case 7:
return EDIT_KEY_CTRL_G;
case 8:
return EDIT_KEY_CTRL_H;
case 9:
return EDIT_KEY_TAB;
case 10:
return EDIT_KEY_CTRL_J;
case 13: /* CR */
return EDIT_KEY_ENTER;
case 11:
return EDIT_KEY_CTRL_K;
case 12:
return EDIT_KEY_CTRL_L;
case 14:
return EDIT_KEY_CTRL_N;
case 15:
return EDIT_KEY_CTRL_O;
case 16:
return EDIT_KEY_CTRL_P;
case 18:
return EDIT_KEY_CTRL_R;
case 20:
return EDIT_KEY_CTRL_T;
case 21:
return EDIT_KEY_CTRL_U;
case 22:
return EDIT_KEY_CTRL_V;
case 23:
return EDIT_KEY_CTRL_W;
case 27: /* ESC */
esc = 0;
return EDIT_KEY_NONE;
case 127:
return EDIT_KEY_BACKSPACE;
default:
return c;
}
}
static void edit_read_char(int sock, void *eloop_ctx, void *sock_ctx)
{
static int last_tab = 0;
enum edit_key_code c;
c = edit_read_key(sock);
if (c != EDIT_KEY_TAB && c != EDIT_KEY_NONE)
last_tab = 0;
switch (c) {
case EDIT_KEY_NONE:
break;
case EDIT_KEY_EOF:
edit_eof_cb(edit_cb_ctx);
break;
case EDIT_KEY_TAB:
complete(last_tab);
last_tab = 1;
break;
case EDIT_KEY_UP:
case EDIT_KEY_CTRL_P:
history_prev();
break;
case EDIT_KEY_DOWN:
case EDIT_KEY_CTRL_N:
history_next();
break;
case EDIT_KEY_RIGHT:
case EDIT_KEY_CTRL_F:
move_right();
break;
case EDIT_KEY_LEFT:
case EDIT_KEY_CTRL_B:
move_left();
break;
case EDIT_KEY_CTRL_RIGHT:
move_word_right();
break;
case EDIT_KEY_CTRL_LEFT:
move_word_left();
break;
case EDIT_KEY_DELETE:
delete_current();
break;
case EDIT_KEY_END:
move_end();
break;
case EDIT_KEY_HOME:
case EDIT_KEY_CTRL_A:
move_start(); move_start();
break; break;
case 4: /* ^D */ case EDIT_KEY_F2:
history_debug_dump();
break;
case EDIT_KEY_CTRL_D:
if (cmdbuf_len > 0) { if (cmdbuf_len > 0) {
delete_current(); delete_current();
return; return;
@ -576,50 +740,36 @@ static void edit_read_char(int sock, void *eloop_ctx, void *sock_ctx)
printf("\n"); printf("\n");
edit_eof_cb(edit_cb_ctx); edit_eof_cb(edit_cb_ctx);
break; break;
case 5: /* ^E */ case EDIT_KEY_CTRL_E:
move_end(); move_end();
break; break;
case 8: /* ^H = BS */ case EDIT_KEY_CTRL_H:
case EDIT_KEY_BACKSPACE:
delete_left(); delete_left();
break; break;
case 9: /* ^I = TAB */ case EDIT_KEY_ENTER:
complete(last_tab); case EDIT_KEY_CTRL_J:
last_tab = 1;
break;
case 10: /* NL */
case 13: /* CR */
process_cmd(); process_cmd();
break; break;
case 11: /* ^K */ case EDIT_KEY_CTRL_K:
clear_right(); clear_right();
break; break;
case 12: /* ^L */ case EDIT_KEY_CTRL_L:
edit_clear_line(); edit_clear_line();
edit_redraw(); edit_redraw();
break; break;
case 14: /* ^N */ case EDIT_KEY_CTRL_R:
history_next();
break;
case 16: /* ^P */
history_prev();
break;
case 18: /* ^R */
/* TODO: search history */ /* TODO: search history */
break; break;
case 21: /* ^U */ case EDIT_KEY_CTRL_U:
clear_left(); clear_left();
break; break;
case 23: /* ^W */ case EDIT_KEY_CTRL_W:
delete_word(); delete_word();
break; break;
case 27: /* ESC */
esc = 0;
break;
case 127: /* DEL */
delete_left();
break;
default: default:
insert_char(c); if (c >= 32 && c <= 255)
insert_char(c);
break; break;
} }
} }