Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor get_key #189

Merged
merged 4 commits into from
Jun 8, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
133 changes: 72 additions & 61 deletions pick.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
errx(1, #capability ": unknown terminfo capability"); \
} while (0)

enum {
enum key {
UNKNOWN,
ALT_ENTER,
BACKSPACE,
Expand All @@ -46,7 +46,8 @@ enum {
DOWN,
LEFT,
PAGE_DOWN,
PAGE_UP
PAGE_UP,
PRINTABLE
};

struct choice {
Expand All @@ -63,7 +64,7 @@ static void delete_between(char *, size_t, size_t, size_t);
static char *eager_strpbrk(const char *, const char *);
static void filter_choices(void);
static char *get_choices(void);
static int get_key(char *, size_t, size_t *);
static enum key get_key(char *, size_t, size_t *);
static void handle_sigint(int);
static int isu8cont(unsigned char);
static int isu8start(unsigned char);
Expand Down Expand Up @@ -275,7 +276,7 @@ selected_choice(void)
size_t cursor_position, i, j, length;
size_t xscroll = 0;
char buf[6];
int choices_count, key, word_position;
int choices_count, word_position;
int selection = 0;
int yscroll = 0;

Expand Down Expand Up @@ -327,8 +328,7 @@ selected_choice(void)
tty_putp(cursor_normal, 0);
fflush(tty_out);

key = get_key(buf, sizeof(buf), &length);
switch (key) {
switch (get_key(buf, sizeof(buf), &length)) {
case ENTER:
if (choices_count > 0)
return &choices.v[selection];
Expand Down Expand Up @@ -456,10 +456,7 @@ selected_choice(void)
else
yscroll = selection = 0;
break;
default:
if (!isu8start(buf[0]) && !isprint(buf[0]))
continue;

case PRINTABLE:
if (query_length + length >= query_size) {
query_size = 2*query_length + length;
if ((query = reallocarray(query, query_size,
Expand All @@ -478,6 +475,8 @@ selected_choice(void)
query[query_length] = '\0';
filter_choices();
selection = yscroll = 0;
case UNKNOWN:
break;
}
}
}
Expand Down Expand Up @@ -785,89 +784,101 @@ print_choices(int offset, int selection)
return i;
}

int
enum key
get_key(char *buf, size_t size, size_t *nread)
{
#define KEY(k, s) { k, s, sizeof(s) - 1 }
static struct {
enum key key;
const char *s;
size_t length;
int key;
} keys[] = {
{ "\n", 1, ENTER },
{ "\r", 1, ENTER },
{ "\177", 1, BACKSPACE },
{ "\001", 1, CTRL_A },
{ "\002", 1, LEFT },
{ "\004", 1, DEL },
{ "\005", 1, CTRL_E },
{ "\006", 1, RIGHT },
{ "\013", 1, CTRL_K },
{ "\016", 1, DOWN },
{ "\020", 1, UP },
{ "\025", 1, CTRL_U },
{ "\027", 1, CTRL_W },
{ "\033\n", 2, ALT_ENTER },
{ "\033\r", 2, ALT_ENTER },
{ "\033[A", 3, UP },
{ "\033OA", 3, UP },
{ "\033[B", 3, DOWN },
{ "\033OB", 3, DOWN },
{ "\033[C", 3, RIGHT },
{ "\033OC", 3, RIGHT },
{ "\033[D", 3, LEFT },
{ "\033OD", 3, LEFT },
{ "\033[3~", 4, DEL },
{ "\033O3~", 4, DEL },
{ "\033[6~", 4, PAGE_DOWN },
{ "\033[5~", 4, PAGE_UP },
{ NULL, 0, 0 },
KEY(ALT_ENTER, "\033\n"),
KEY(ALT_ENTER, "\033\r"),
KEY(BACKSPACE, "\177"),
KEY(CTRL_A, "\001"),
KEY(CTRL_E, "\005"),
KEY(CTRL_K, "\013"),
KEY(CTRL_U, "\025"),
KEY(CTRL_W, "\027"),
KEY(DEL, "\004"),
KEY(DEL, "\033O3~"),
KEY(DEL, "\033[3~"),
KEY(DOWN, "\016"),
KEY(DOWN, "\033OB"),
KEY(DOWN, "\033[B"),
KEY(ENTER, "\n"),
KEY(ENTER, "\r"),
KEY(LEFT, "\002"),
KEY(LEFT, "\033OD"),
KEY(LEFT, "\033[D"),
KEY(PAGE_DOWN, "\033[6~"),
KEY(PAGE_UP, "\033[5~"),
KEY(RIGHT, "\006"),
KEY(RIGHT, "\033OC"),
KEY(RIGHT, "\033[C"),
KEY(UP, "\020"),
KEY(UP, "\033OA"),
KEY(UP, "\033[A"),
{ 0, NULL, 0 },
};
int c, i;

*nread = 0;
getc:
buf[(*nread)++] = tty_getc();
size--;
for (i = 0; keys[i].s != NULL; i++) {
if (*nread > keys[i].length
|| strncmp(buf, keys[i].s, *nread) != 0)
continue;
for (; size > 0; size--) {
buf[(*nread)++] = tty_getc();

if (*nread == keys[i].length)
return keys[i].key;
for (i = 0; keys[i].s != NULL; i++) {
if (*nread > keys[i].length
|| strncmp(buf, keys[i].s, *nread) != 0)
continue;

/* Partial match found, continue reading. */
if (size > 0)
goto getc;
if (*nread == keys[i].length)
return keys[i].key;

/* Partial match found, continue reading. */
break;
}
if (keys[i].s == NULL)
break;
}

if (*nread > 1 && buf[0] == '\033' && (buf[1] == '[' || buf[1] == 'O')) {
/*
* A escape sequence which is not a supported key is being read.
* Discard the rest of the sequence.
* An escape sequence which is not a supported key is being
* read. Discard the rest of the sequence.
*/
for (;;) {
c = buf[(*nread) - 1];
while (c < '@' || c > '~')
c = tty_getc();
if (c >= '@' && c <= '~')
break;
}

return UNKNOWN;
}

if (!isu8start(buf[0]))
if (!isu8start(buf[0])) {
if (isprint(buf[0]))
return PRINTABLE;

return UNKNOWN;
}

/*
* Ensure a whole Unicode character is read. The number of MSBs in the
* first octet of a Unicode character is equal to the number of octets
* the character consists of, followed by a zero. Therefore, as long as
* the MSB is not zero there is still bytes left to read.
*/
while ((((unsigned int)buf[0] << *nread) & 0x80) == 0x80 && size-- > 0)
for (;;) {
if ((((unsigned int)buf[0] << *nread) & 0x80) == 0)
break;
if (size == 0)
return UNKNOWN;

buf[(*nread)++] = tty_getc();
size--;
}

return UNKNOWN;
return PRINTABLE;
}

int
Expand Down