Adjust termkey_strpkey() API more like strptime(); return pointer to end of recognised section, allows for stream parsing

This commit is contained in:
Paul LeoNerd Evans 2011-04-01 13:49:20 +01:00
parent dbb13defb7
commit 88230407fe
4 changed files with 40 additions and 57 deletions

View File

@ -5,88 +5,77 @@ int main(int argc, char *argv[])
{
TermKey *tk;
TermKeyKey key;
TermKeyResult res;
#define CLEAR_KEY do { key.type = -1; key.code.codepoint = -1; key.modifiers = -1; key.utf8[0] = 0; } while(0)
plan_tests(48);
plan_tests(38);
tk = termkey_new(0, TERMKEY_FLAG_NOTERMIOS);
CLEAR_KEY;
res = termkey_strpkey(tk, "A", &key, 0);
is_int(res, TERMKEY_RES_KEY, "result for unicode/A/0");
termkey_strpkey(tk, "A", &key, 0);
is_int(key.type, TERMKEY_TYPE_UNICODE, "key.type for unicode/A/0");
is_int(key.code.codepoint, 'A', "key.code.codepoint for unicode/A/0");
is_int(key.code.codepoint, 'A', "key.code.codepoint for unicode/A/0");
is_int(key.modifiers, 0, "key.modifiers for unicode/A/0");
is_str(key.utf8, "A", "key.utf8 for unicode/A/0");
CLEAR_KEY;
res = termkey_strpkey(tk, "C-b", &key, 0);
is_int(res, TERMKEY_RES_KEY, "result for unicode/b/CTRL");
termkey_strpkey(tk, "C-b", &key, 0);
is_int(key.type, TERMKEY_TYPE_UNICODE, "key.type for unicode/b/CTRL");
is_int(key.code.codepoint, 'b', "key.code.codepoint for unicode/b/CTRL");
is_int(key.code.codepoint, 'b', "key.code.codepoint for unicode/b/CTRL");
is_int(key.modifiers, TERMKEY_KEYMOD_CTRL, "key.modifiers for unicode/b/CTRL");
is_str(key.utf8, "b", "key.utf8 for unicode/b/CTRL");
CLEAR_KEY;
res = termkey_strpkey(tk, "Ctrl-b", &key, TERMKEY_FORMAT_LONGMOD);
is_int(res, TERMKEY_RES_KEY, "result for unicode/b/CTRL longmod");
termkey_strpkey(tk, "Ctrl-b", &key, TERMKEY_FORMAT_LONGMOD);
is_int(key.type, TERMKEY_TYPE_UNICODE, "key.type for unicode/b/CTRL longmod");
is_int(key.code.codepoint, 'b', "key.code.codepoint for unicode/b/CTRL longmod");
is_int(key.code.codepoint, 'b', "key.code.codepoint for unicode/b/CTRL longmod");
is_int(key.modifiers, TERMKEY_KEYMOD_CTRL, "key.modifiers for unicode/b/CTRL longmod");
is_str(key.utf8, "b", "key.utf8 for unicode/b/CTRL longmod");
CLEAR_KEY;
res = termkey_strpkey(tk, "^B", &key, TERMKEY_FORMAT_CARETCTRL);
is_int(res, TERMKEY_RES_KEY, "result for unicode/b/CTRL caretctrl");
termkey_strpkey(tk, "^B", &key, TERMKEY_FORMAT_CARETCTRL);
is_int(key.type, TERMKEY_TYPE_UNICODE, "key.type for unicode/b/CTRL caretctrl");
is_int(key.code.codepoint, 'b', "key.code.codepoint for unicode/b/CTRL caretctrl");
is_int(key.code.codepoint, 'b', "key.code.codepoint for unicode/b/CTRL caretctrl");
is_int(key.modifiers, TERMKEY_KEYMOD_CTRL, "key.modifiers for unicode/b/CTRL caretctrl");
is_str(key.utf8, "b", "key.utf8 for unicode/b/CTRL caretctrl");
CLEAR_KEY;
res = termkey_strpkey(tk, "A-c", &key, 0);
is_int(res, TERMKEY_RES_KEY, "result for unicode/c/ALT");
termkey_strpkey(tk, "A-c", &key, 0);
is_int(key.type, TERMKEY_TYPE_UNICODE, "key.type for unicode/c/ALT");
is_int(key.code.codepoint, 'c', "key.code.codepoint for unicode/c/ALT");
is_int(key.code.codepoint, 'c', "key.code.codepoint for unicode/c/ALT");
is_int(key.modifiers, TERMKEY_KEYMOD_ALT, "key.modifiers for unicode/c/ALT");
is_str(key.utf8, "c", "key.utf8 for unicode/c/ALT");
CLEAR_KEY;
res = termkey_strpkey(tk, "Alt-c", &key, TERMKEY_FORMAT_LONGMOD);
is_int(res, TERMKEY_RES_KEY, "result for unicode/c/ALT longmod");
termkey_strpkey(tk, "Alt-c", &key, TERMKEY_FORMAT_LONGMOD);
is_int(key.type, TERMKEY_TYPE_UNICODE, "key.type for unicode/c/ALT longmod");
is_int(key.code.codepoint, 'c', "key.code.codepoint for unicode/c/ALT longmod");
is_int(key.code.codepoint, 'c', "key.code.codepoint for unicode/c/ALT longmod");
is_int(key.modifiers, TERMKEY_KEYMOD_ALT, "key.modifiers for unicode/c/ALT longmod");
is_str(key.utf8, "c", "key.utf8 for unicode/c/ALT longmod");
CLEAR_KEY;
res = termkey_strpkey(tk, "M-c", &key, TERMKEY_FORMAT_ALTISMETA);
is_int(res, TERMKEY_RES_KEY, "result for unicode/c/ALT altismeta");
termkey_strpkey(tk, "M-c", &key, TERMKEY_FORMAT_ALTISMETA);
is_int(key.type, TERMKEY_TYPE_UNICODE, "key.type for unicode/c/ALT altismeta");
is_int(key.code.codepoint, 'c', "key.code.codepoint for unicode/c/ALT altismeta");
is_int(key.code.codepoint, 'c', "key.code.codepoint for unicode/c/ALT altismeta");
is_int(key.modifiers, TERMKEY_KEYMOD_ALT, "key.modifiers for unicode/c/ALT altismeta");
is_str(key.utf8, "c", "key.utf8 for unicode/c/ALT altismeta");
CLEAR_KEY;
res = termkey_strpkey(tk, "Meta-c", &key, TERMKEY_FORMAT_ALTISMETA|TERMKEY_FORMAT_LONGMOD);
is_int(res, TERMKEY_RES_KEY, "result for unicode/c/ALT altismeta+longmod");
termkey_strpkey(tk, "Meta-c", &key, TERMKEY_FORMAT_ALTISMETA|TERMKEY_FORMAT_LONGMOD);
is_int(key.type, TERMKEY_TYPE_UNICODE, "key.type for unicode/c/ALT altismeta+longmod");
is_int(key.code.codepoint, 'c', "key.code.codepoint for unicode/c/ALT altismeta+longmod");
is_int(key.code.codepoint, 'c', "key.code.codepoint for unicode/c/ALT altismeta+longmod");
is_int(key.modifiers, TERMKEY_KEYMOD_ALT, "key.modifiers for unicode/c/ALT altismeta+longmod");
is_str(key.utf8, "c", "key.utf8 for unicode/c/ALT altismeta+longmod");
CLEAR_KEY;
res = termkey_strpkey(tk, "Up", &key, 0);
is_int(res, TERMKEY_RES_KEY, "result for sym/Up/0");
termkey_strpkey(tk, "Up", &key, 0);
is_int(key.type, TERMKEY_TYPE_KEYSYM, "key.type for sym/Up/0");
is_int(key.code.sym, TERMKEY_SYM_UP, "key.code.codepoint for sym/Up/0");
is_int(key.modifiers, 0, "key.modifiers for sym/Up/0");
CLEAR_KEY;
res = termkey_strpkey(tk, "F5", &key, 0);
is_int(res, TERMKEY_RES_KEY, "result for func/5/0");
termkey_strpkey(tk, "F5", &key, 0);
is_int(key.type, TERMKEY_TYPE_FUNCTION, "key.type for func/5/0");
is_int(key.code.number, 5, "key.code.number for func/5/0");
is_int(key.modifiers, 0, "key.modifiers for func/5/0");

View File

@ -1080,7 +1080,7 @@ size_t termkey_strfkey(TermKey *tk, char *buffer, size_t len, TermKeyKey *key, T
return pos;
}
TermKeyResult termkey_strpkey(TermKey *tk, const char *str, TermKeyKey *key, TermKeyFormat format)
char *termkey_strpkey(TermKey *tk, const char *str, TermKeyKey *key, TermKeyFormat format)
{
struct modnames *mods = &modnames[!!(format & TERMKEY_FORMAT_LONGMOD) +
!!(format & TERMKEY_FORMAT_ALTISMETA) * 2];
@ -1088,22 +1088,19 @@ TermKeyResult termkey_strpkey(TermKey *tk, const char *str, TermKeyKey *key, Ter
key->modifiers = 0;
if((format & TERMKEY_FORMAT_CARETCTRL) && str[0] == '^' && str[1]) {
TermKeyResult res = termkey_strpkey(tk, str+1, key, format & ~TERMKEY_FORMAT_CARETCTRL);
str = termkey_strpkey(tk, str+1, key, format & ~TERMKEY_FORMAT_CARETCTRL);
if(res != TERMKEY_RES_KEY)
return res;
if(key->type != TERMKEY_TYPE_UNICODE)
return TERMKEY_RES_NONE;
if(key->code.codepoint < '@' || key->code.codepoint > '_')
return TERMKEY_RES_NONE;
if(key->modifiers != 0)
return TERMKEY_RES_NONE;
if(!str ||
key->type != TERMKEY_TYPE_UNICODE ||
key->code.codepoint < '@' || key->code.codepoint > '_' ||
key->modifiers != 0)
return NULL;
if(key->code.codepoint >= 'A' && key->code.codepoint <= 'Z')
key->code.codepoint += 0x20;
key->modifiers = TERMKEY_KEYMOD_CTRL;
fill_utf8(key);
return res;
return (char *)str;
}
const char *hyphen;
@ -1125,22 +1122,25 @@ TermKeyResult termkey_strpkey(TermKey *tk, const char *str, TermKeyKey *key, Ter
}
size_t nbytes;
char *endstr;
if(parse_utf8((unsigned char *)str, strlen(str), &key->code.codepoint, &nbytes) == TERMKEY_RES_KEY &&
nbytes == strlen(str)) {
key->type = TERMKEY_TYPE_UNICODE;
fill_utf8(key);
str += nbytes;
}
else if((key->code.sym = termkey_keyname2sym(tk, str)) != TERMKEY_SYM_UNKNOWN) {
else if((endstr = termkey_lookup_keyname(tk, str, &key->code.sym))) {
key->type = TERMKEY_TYPE_KEYSYM;
str = endstr;
}
else if(sscanf(str, "F%d", &key->code.number) == 1) {
else if(sscanf(str, "F%d%n", &key->code.number, &nbytes) == 1) {
key->type = TERMKEY_TYPE_FUNCTION;
str += nbytes;
}
// TODO: Consider mouse events?
else {
return TERMKEY_RES_NONE;
}
else
return NULL;
return TERMKEY_RES_KEY;
return (char *)str;
}

View File

@ -190,8 +190,8 @@ typedef enum {
#define TERMKEY_FORMAT_VIM (TERMKEY_FORMAT_ALTISMETA|TERMKEY_FORMAT_WRAPBRACKET)
size_t termkey_strfkey(TermKey *tk, char *buffer, size_t len, TermKeyKey *key, TermKeyFormat format);
TermKeyResult termkey_strpkey(TermKey *tk, const char *str, TermKeyKey *key, TermKeyFormat format);
size_t termkey_strfkey(TermKey *tk, char *buffer, size_t len, TermKeyKey *key, TermKeyFormat format);
char *termkey_strpkey(TermKey *tk, const char *str, TermKeyKey *key, TermKeyFormat format);
// Old name for termkey_strfkey()
size_t termkey_snprint_key(TermKey *tk, char *buffer, size_t len, TermKeyKey *key, TermKeyFormat format);

View File

@ -5,7 +5,7 @@ termkey_strpkey \- parse a string representing a key event
.nf
.B #include <termkey.h>
.sp
.BI "size_t termkey_strpkey(TermKey *" tk ", const char *" str ",
.BI "char *termkey_strpkey(TermKey *" tk ", const char *" str ",
.BI " TermKeyKey " key ", TermKeyFormat " format );
.fi
.sp
@ -26,13 +26,7 @@ Use the name "Meta" or the letter "M" instead of "Alt" or "A".
.PP
The \fBTERMKEY_FORMAT_WRAPBRACKET\fP and \fBTERMKEY_FORMAT_MOUSE_POS\fP options are currently not supported by \fBtermkey_strpkey\fP(). When returning a \fBTERMKEY_TYPE_UNICODE\fP key structure, this function will fill in the \fIutf8\fP member.
.SH "RETURN VALUE"
\fBtermkey_strpkey\fP() returns one of the following constants:
.TP
.B TERMKEY_RES_KEY
A key structure was successfully parsed.
.TP
.B TERMKEY_RES_NONE
No key was recognised in the string buffer.
After a successful parse, \fBtermkey_strpkey\fP() returns a pointer to the first character of the input it did not consume. If the input string contains more characters then this will point at the first character beyond. If the entire input string was consumed, then this will point at a null byte. If \fBtermkey_strpkey\fP() fails to parse, it returns \fBNULL\fP. After a failed parse, the \fIkey\fP structure may contain partial or invalid results. The structure will only be valid if the function returns a non-\fBNULL\fP result.
.SH "SEE ALSO"
.BR termkey_new (3),
.BR termkey_strfkey (3)