Distinguish <c-h> and Backspace on terminals where that is possible.

Different terminals send different codes to indicate backspace, usually one of
\x08 or \x7f, so Kakoune blindly treated both as backspace. However, a given
terminal is only likely to use one of those, and mnemonic control codes like
<c-h> are a precious resource so we should endeavour to keep backspace and
<c-h> separate when we can. Luckily, termios tells us what code our terminal is
currently using, and Kakoune already reads the information at startup, so we can
just use that information.

Thanks to @krobelus for figuring out the C++ syntax required.

Fixes #3863.
This commit is contained in:
Tim Allen 2020-11-24 19:14:04 +11:00
parent df7b33bc7b
commit a7ed1f03fb

View File

@ -610,16 +610,19 @@ Optional<Key> NCursesUI::get_next_key()
if (not c)
return {};
static constexpr auto convert = [](Codepoint c) -> Codepoint {
const cc_t erase = m_original_termios.c_cc[VERASE];
auto convert = [erase](Codepoint c) -> Codepoint {
if (c == control('m') or c == control('j'))
return Key::Return;
if (c == control('i'))
return Key::Tab;
if (c == control('h') or c == 127)
if (c == erase)
return Key::Backspace;
if (c == 127) // when it's not backspace
return Key::Delete;
return c;
};
auto parse_key = [](unsigned char c) -> Key {
auto parse_key = [&convert](unsigned char c) -> Key {
if (Codepoint cp = convert(c); cp > 255)
return Key{cp};
if (c == control('z'))
@ -652,7 +655,7 @@ Optional<Key> NCursesUI::get_next_key()
return Key{utf8::codepoint(CharIterator{c}, Sentinel{})};
};
auto parse_csi = [this]() -> Optional<Key> {
auto parse_csi = [this, &convert]() -> Optional<Key> {
auto next_char = [] { return get_char().value_or((unsigned char)0xff); };
int params[16] = {};
auto c = next_char();