diff options
-rw-r--r-- | man/termkey_strfkey.3 | 2 | ||||
-rw-r--r-- | man/termkey_strpkey.3 | 3 | ||||
-rw-r--r-- | t/12strpkey.c | 10 | ||||
-rw-r--r-- | termkey.c | 100 |
4 files changed, 86 insertions, 29 deletions
diff --git a/man/termkey_strfkey.3 b/man/termkey_strfkey.3 index 363e576..c30f12e 100644 --- a/man/termkey_strfkey.3 +++ b/man/termkey_strfkey.3 @@ -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". diff --git a/man/termkey_strpkey.3 b/man/termkey_strpkey.3 index 89efb1c..cd4f311 100644 --- a/man/termkey_strpkey.3 +++ b/man/termkey_strpkey.3 @@ -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 diff --git a/t/12strpkey.c b/t/12strpkey.c index 099fe9a..c532b6c 100644 --- a/t/12strpkey.c +++ b/t/12strpkey.c @@ -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); @@ -94,6 +94,14 @@ int main(int argc, char *argv[]) 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"); is_int(key.code.sym, TERMKEY_SYM_UP, "key.code.codepoint for sym/Up/0"); @@ -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; } |