Added TERMKEY_FORMAT_LOWERSPACE for strpkey() also

This commit is contained in:
Paul LeoNerd Evans 2013-08-26 02:23:19 +01:00
parent 3b2d8eb813
commit 8e503baed8
4 changed files with 86 additions and 29 deletions

View File

@ -34,7 +34,7 @@ Use spaces instead of hyphens to separate the modifier name(s) from the base key
Use lowercase for the modifier name.
.TP
.B TERMKEY_FORMAT_LOWERSPACE
Use lowercase for the key name instead of camelCase (for example "\f(CWpage down\fP" instead of "\f(CWPageDown\fP").
Use lowercase with spaces in for the key name instead of camelCase (for example "\f(CWpage down\fP" instead of "\f(CWPageDown\fP").
.TP
.B TERMKEY_FORMAT_MOUSE_POS
If the event is a mouse event, include the position rendered as "\f(CW@ (col,line)\fP".

View File

@ -29,6 +29,9 @@ Expect spaces instead of hyphens to separate the modifer name(s) from the base k
.TP
.B TERMKEY_FORMAT_LOWERMOD
Expect lowercase for the modifier name
.TP
.B TERMKEY_FORMAT_LOWERSPACE
Expect lowercase with spaces in for the key name instead of camelCase (for example "\f(CWpage down\fP" instead of "\f(CWPageDown\fP").
.PP
Before returning, this function canonicalises the \fIkey\fP structure according to the rules given for \fBtermkey_canonicalise\fP(3).
.PP

View File

@ -9,7 +9,7 @@ int main(int argc, char *argv[])
#define CLEAR_KEY do { key.type = -1; key.code.codepoint = -1; key.modifiers = -1; key.utf8[0] = 0; } while(0)
plan_tests(58);
plan_tests(62);
tk = termkey_new_abstract("vt100", 0);
@ -93,6 +93,14 @@ int main(int argc, char *argv[])
is_str(key.utf8, "c", "key.utf8 for unicode/c/ALT altismeta+long/space_lowermod");
is_str(endp, "", "consumed entire input for unicode/c/ALT altismeta+long/space+lowermod");
CLEAR_KEY;
endp = termkey_strpkey(tk, "ctrl alt page up", &key, TERMKEY_FORMAT_LONGMOD|TERMKEY_FORMAT_SPACEMOD|TERMKEY_FORMAT_LOWERMOD|TERMKEY_FORMAT_LOWERSPACE);
is_int(key.type, TERMKEY_TYPE_KEYSYM, "key.type for sym/PageUp/CTRL+ALT long/space/lowermod+lowerspace");
is_int(key.code.sym, TERMKEY_SYM_PAGEUP, "key.code.codepoint for sym/PageUp/CTRL+ALT long/space/lowermod+lowerspace");
is_int(key.modifiers, TERMKEY_KEYMOD_ALT | TERMKEY_KEYMOD_CTRL,
"key.modifiers for sym/PageUp/CTRL+ALT long/space/lowermod+lowerspace");
is_str(endp, "", "consumed entire input for sym/PageUp/CTRL+ALT long/space/lowermod+lowerspace");
CLEAR_KEY;
endp = termkey_strpkey(tk, "Up", &key, 0);
is_int(key.type, TERMKEY_TYPE_KEYSYM, "key.type for sym/Up/0");

100
termkey.c
View File

@ -191,6 +191,63 @@ static const char *res2str(TermKeyResult res)
}
#endif
/* Similar to snprintf(str, size, "%s", src) except it turns CamelCase into
* space separated values
*/
static int snprint_cameltospaces(char *str, size_t size, const char *src)
{
int prev_lower = 0;
size_t l = 0;
while(*src && l < size) {
if(isupper(*src) && prev_lower) {
if(str)
str[l++] = ' ';
if(l >= size)
return -1;
}
prev_lower = islower(*src);
str[l++] = tolower(*src++);
}
if(l >= size)
return -1;
str[l] = 0;
return l;
}
/* Similar to strcmp(str, strcamel, n) except that:
* it compares CamelCase in strcamel with space separated values in str;
* it takes char**s and updates them
* n counts bytes of str, not strcamel
*/
static int strpncmp_camel(const char **strp, const char **strcamelp, size_t n)
{
const char *str = *strp, *strcamel = *strcamelp;
int prev_lower = 0;
for( ; (*str || *strcamel) && n; n--) {
char b = tolower(*strcamel);
if(isupper(*strcamel) && prev_lower) {
if(*str != ' ')
break;
str++;
if(*str != b)
break;
}
else
if(*str != b)
break;
prev_lower = islower(*strcamel);
str++;
strcamel++;
}
*strp = str;
*strcamelp = strcamel;
return *str - *strcamel;
}
static TermKey *termkey_alloc(void)
{
TermKey *tk = malloc(sizeof(TermKey));
@ -1114,7 +1171,7 @@ const char *termkey_get_keyname(TermKey *tk, TermKeySym sym)
return "UNKNOWN";
}
const char *termkey_lookup_keyname(TermKey *tk, const char *str, TermKeySym *sym)
static const char *termkey_lookup_keyname_format(TermKey *tk, const char *str, TermKeySym *sym, TermKeyFormat format)
{
/* We store an array, so we can't do better than a linear search. Doesn't
* matter because user won't be calling this too often */
@ -1124,13 +1181,25 @@ const char *termkey_lookup_keyname(TermKey *tk, const char *str, TermKeySym *sym
if(!thiskey)
continue;
size_t len = strlen(thiskey);
if(strncmp(str, thiskey, len) == 0)
return (char *)str + len;
if(format & TERMKEY_FORMAT_LOWERSPACE) {
const char *thisstr = str;
if(strpncmp_camel(&thisstr, &thiskey, len) == 0)
return thisstr;
}
else {
if(strncmp(str, thiskey, len) == 0)
return (char *)str + len;
}
}
return NULL;
}
const char *termkey_lookup_keyname(TermKey *tk, const char *str, TermKeySym *sym)
{
return termkey_lookup_keyname_format(tk, str, sym, 0);
}
TermKeySym termkey_keyname2sym(TermKey *tk, const char *keyname)
{
TermKeySym sym;
@ -1171,29 +1240,6 @@ size_t termkey_snprint_key(TermKey *tk, char *buffer, size_t len, TermKeyKey *ke
return termkey_strfkey(tk, buffer, len, key, format);
}
/* Similar to snprintf(str, size, "%s", src) except it turns CamelCase into
* space separated values
*/
static int snprint_cameltospaces(char *str, size_t size, const char *src)
{
int prev_lower = 0;
size_t l = 0;
while(*src && l < size) {
if(isupper(*src) && prev_lower) {
if(str)
str[l++] = ' ';
if(l >= size)
return -1;
}
prev_lower = islower(*src);
str[l++] = tolower(*src++);
}
if(l >= size)
return -1;
str[l] = 0;
return l;
}
static struct modnames {
const char *shift, *alt, *ctrl;
}
@ -1381,7 +1427,7 @@ const char *termkey_strpkey(TermKey *tk, const char *str, TermKeyKey *key, TermK
ssize_t snbytes;
const char *endstr;
if((endstr = termkey_lookup_keyname(tk, str, &key->code.sym))) {
if((endstr = termkey_lookup_keyname_format(tk, str, &key->code.sym, format))) {
key->type = TERMKEY_TYPE_KEYSYM;
str = endstr;
}