summaryrefslogtreecommitdiff
path: root/src/keys.cc
diff options
context:
space:
mode:
authorMaxime Coste <frrrwww@gmail.com>2014-11-09 13:02:01 +0000
committerMaxime Coste <frrrwww@gmail.com>2014-11-09 13:02:01 +0000
commit40d649f836edf0c44c2548e89c2c3ab869236e82 (patch)
treeea538ef095d7ab375b6e6680c683192c9d74abc0 /src/keys.cc
parent766df0490c6da2b576ab5a98c9b7fa853eb13bd5 (diff)
refactor parse_keys
Diffstat (limited to 'src/keys.cc')
-rw-r--r--src/keys.cc104
1 files changed, 43 insertions, 61 deletions
diff --git a/src/keys.cc b/src/keys.cc
index 58292fd7..30bdbe41 100644
--- a/src/keys.cc
+++ b/src/keys.cc
@@ -41,75 +41,57 @@ static const KeyAndName keynamemap[] = {
KeyList parse_keys(StringView str)
{
KeyList result;
- using PassPolicy = utf8::InvalidPolicy::Pass;
- using Utf8It = utf8::iterator<const char*, PassPolicy>;
+ using Utf8It = utf8::iterator<const char*>;
for (Utf8It it = str.begin(), str_end = str.end(); it < str_end; ++it)
{
- if (*it == '<')
+ if (*it != '<')
{
- Utf8It end_it = it;
- while (end_it < str_end and *end_it != '>')
- ++end_it;
+ result.push_back({Key::Modifiers::None, *it});
+ continue;
+ }
- if (end_it < str_end)
- {
- Key::Modifiers modifier = Key::Modifiers::None;
+ Utf8It end_it = it;
+ skip_while(end_it, str_end, [](char c) { return c != '>'; });
+ if (end_it == str_end)
+ {
+ result.push_back({Key::Modifiers::None, *it});
+ continue;
+ }
- StringView keyname{it.base()+1, end_it.base()};
- if (keyname.length() > 2)
- {
- if (tolower(keyname[0]) == 'c' and keyname[1] == '-')
- {
- modifier = Key::Modifiers::Control;
- keyname = keyname.substr(2_byte);
- }
- if (tolower(keyname[0]) == 'a' and keyname[1] == '-')
- {
- modifier = Key::Modifiers::Alt;
- keyname = keyname.substr(2_byte);
- }
- }
- if (keyname.char_length() == 1)
- {
- result.push_back(Key{ modifier, utf8::codepoint<PassPolicy>(keyname.begin(),keyname.end()) });
- it = end_it;
- continue;
- }
- auto name_it = find_if(keynamemap, [&keyname](const KeyAndName& item)
- { return item.first == keyname; });
- if (name_it != end(keynamemap))
- {
- Key key = canonicalize_ifn(Key{ modifier, name_it->second });
- result.push_back(key);
- it = end_it;
- continue;
- }
- if ((keyname[0] == 'f' or keyname[0] == 'F') and
- keyname.length() <= 3)
- {
+ Key::Modifiers modifier = Key::Modifiers::None;
- int val = 0;
- for (auto i = 1_byte; i < keyname.length(); ++i)
- {
- char c = keyname[i];
- if (c >= '0' and c <= '9')
- val = val*10 + c - '0';
- else
- {
- val = -1;
- break;
- }
- }
- if (val >= 1 and val <= 12)
- {
- result.push_back(Key{ modifier, Key::F1 + (val - 1) });
- it = end_it;
- continue;
- }
- }
+ StringView desc{it.base()+1, end_it.base()};
+ if (desc.length() > 2 and desc[1] == '-')
+ {
+ switch(tolower(desc[0]))
+ {
+ case 'c': modifier = Key::Modifiers::Control; break;
+ case 'a': modifier = Key::Modifiers::Alt; break;
+ default:
+ throw runtime_error("unable to parse modifier in " +
+ StringView{it.base(), end_it.base()+1});
}
+ desc = desc.substr(2_byte);
+ }
+ auto name_it = find_if(keynamemap, [&desc](const KeyAndName& item)
+ { return item.first == desc; });
+ if (name_it != end(keynamemap))
+ result.push_back(canonicalize_ifn({ modifier, name_it->second }));
+ else if (desc.char_length() == 1)
+ result.push_back(Key{ modifier, desc[0_char] });
+ else if (tolower(desc[0]) == 'f' and desc.length() <= 3)
+ {
+ int val = str_to_int(desc.substr(1_byte));
+ if (val >= 1 and val <= 12)
+ result.push_back(Key{ modifier, Key::F1 + (val - 1) });
+ else
+ throw runtime_error("Only F1 through F12 are supported");
}
- result.push_back({Key::Modifiers::None, *it});
+ else
+ throw runtime_error("Failed to parse " +
+ StringView{it.base(), end_it.base()+1});
+
+ it = end_it;
}
return result;
}