Properly handle unicode in key parsing

Fixes #139
This commit is contained in:
Maxime Coste 2014-06-04 11:51:20 +01:00
parent 72d6ed3575
commit 1533a28394

View File

@ -1,6 +1,7 @@
#include "keys.hh" #include "keys.hh"
#include "utils.hh" #include "utils.hh"
#include "utf8_iterator.hh"
namespace Kakoune namespace Kakoune
{ {
@ -40,19 +41,21 @@ static const KeyAndName keynamemap[] = {
KeyList parse_keys(StringView str) KeyList parse_keys(StringView str)
{ {
KeyList result; KeyList result;
for (ByteCount pos = 0; pos < str.length(); ++pos) using PassPolicy = utf8::InvalidBytePolicy::Pass;
using Utf8It = utf8::utf8_iterator<const char*, PassPolicy>;
for (Utf8It it = str.begin(), str_end = str.end(); it < str_end; ++it)
{ {
if (str[pos] == '<') if (*it == '<')
{ {
ByteCount end_pos = pos; Utf8It end_it = it;
while (end_pos < str.length() and str[end_pos] != '>') while (end_it < str_end and *end_it != '>')
++end_pos; ++end_it;
if (end_pos < str.length()) if (end_it < str_end)
{ {
Key::Modifiers modifier = Key::Modifiers::None; Key::Modifiers modifier = Key::Modifiers::None;
auto keyname = str.substr(pos+1, end_pos - pos - 1); StringView keyname{it.base()+1, end_it.base()};
if (keyname.length() > 2) if (keyname.length() > 2)
{ {
if (tolower(keyname[0]) == 'c' and keyname[1] == '-') if (tolower(keyname[0]) == 'c' and keyname[1] == '-')
@ -66,19 +69,19 @@ KeyList parse_keys(StringView str)
keyname = keyname.substr(2_byte); keyname = keyname.substr(2_byte);
} }
} }
if (keyname.length() == 1) if (keyname.char_length() == 1)
{ {
result.push_back(Key{ modifier, Codepoint(keyname[0]) }); result.push_back(Key{ modifier, utf8::codepoint<PassPolicy>(keyname.begin()) });
pos = end_pos; it = end_it;
continue; continue;
} }
auto it = find_if(keynamemap, [&keyname](const KeyAndName& item) auto name_it = find_if(keynamemap, [&keyname](const KeyAndName& item)
{ return item.first == keyname; }); { return item.first == keyname; });
if (it != end(keynamemap)) if (name_it != end(keynamemap))
{ {
Key key = canonicalize_ifn(Key{ modifier, it->second }); Key key = canonicalize_ifn(Key{ modifier, name_it->second });
result.push_back(key); result.push_back(key);
pos = end_pos; it = end_it;
continue; continue;
} }
if ((keyname[0] == 'f' or keyname[0] == 'F') and if ((keyname[0] == 'f' or keyname[0] == 'F') and
@ -100,13 +103,13 @@ KeyList parse_keys(StringView str)
if (val >= 1 and val <= 12) if (val >= 1 and val <= 12)
{ {
result.push_back(Key{ modifier, Key::F1 + (val - 1) }); result.push_back(Key{ modifier, Key::F1 + (val - 1) });
pos = end_pos; it = end_it;
continue; continue;
} }
} }
} }
} }
result.push_back({Key::Modifiers::None, Codepoint(str[pos])}); result.push_back({Key::Modifiers::None, *it});
} }
return result; return result;
} }