Rework NCurses key parsing to properly handle <a-special key>
This commit is contained in:
parent
f30e164232
commit
34870eb353
15
src/keys.hh
15
src/keys.hh
|
@ -94,9 +94,18 @@ class StringView;
|
||||||
KeyList parse_keys(StringView str);
|
KeyList parse_keys(StringView str);
|
||||||
String key_to_str(Key key);
|
String key_to_str(Key key);
|
||||||
|
|
||||||
constexpr Key alt(Codepoint key) { return { Key::Modifiers::Alt, key }; }
|
constexpr Key alt(Key key)
|
||||||
constexpr Key ctrl(Codepoint key) { return { Key::Modifiers::Control, key }; }
|
{
|
||||||
constexpr Key ctrlalt(Codepoint key) { return { Key::Modifiers::ControlAlt, key }; }
|
return { key.modifiers | Key::Modifiers::Alt, key.key };
|
||||||
|
}
|
||||||
|
constexpr Key ctrl(Key key)
|
||||||
|
{
|
||||||
|
return { key.modifiers | Key::Modifiers::Control, key.key };
|
||||||
|
}
|
||||||
|
constexpr Key ctrlalt(Key key)
|
||||||
|
{
|
||||||
|
return { key.modifiers | Key::Modifiers::ControlAlt, key.key };
|
||||||
|
}
|
||||||
|
|
||||||
constexpr Codepoint encode_coord(DisplayCoord coord) { return (Codepoint)(((int)coord.line << 16) | ((int)coord.column & 0x0000FFFF)); }
|
constexpr Codepoint encode_coord(DisplayCoord coord) { return (Codepoint)(((int)coord.line << 16) | ((int)coord.column & 0x0000FFFF)); }
|
||||||
|
|
||||||
|
|
|
@ -499,9 +499,6 @@ Optional<Key> NCursesUI::get_next_key()
|
||||||
const int c = wgetch(m_window);
|
const int c = wgetch(m_window);
|
||||||
wtimeout(m_window, -1);
|
wtimeout(m_window, -1);
|
||||||
|
|
||||||
if (c == ERR)
|
|
||||||
return {};
|
|
||||||
|
|
||||||
if (c == KEY_MOUSE)
|
if (c == KEY_MOUSE)
|
||||||
{
|
{
|
||||||
MEVENT ev;
|
MEVENT ev;
|
||||||
|
@ -531,6 +528,26 @@ Optional<Key> NCursesUI::get_next_key()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto parse_key = [this](int c) -> Optional<Key> {
|
||||||
|
if (c == ERR)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
switch (c)
|
||||||
|
{
|
||||||
|
case KEY_BACKSPACE: case 127: return {Key::Backspace};
|
||||||
|
case KEY_DC: return {Key::Delete};
|
||||||
|
case KEY_UP: return {Key::Up};
|
||||||
|
case KEY_DOWN: return {Key::Down};
|
||||||
|
case KEY_LEFT: return {Key::Left};
|
||||||
|
case KEY_RIGHT: return {Key::Right};
|
||||||
|
case KEY_PPAGE: return {Key::PageUp};
|
||||||
|
case KEY_NPAGE: return {Key::PageDown};
|
||||||
|
case KEY_HOME: return {Key::Home};
|
||||||
|
case KEY_END: return {Key::End};
|
||||||
|
case KEY_BTAB: return {Key::BackTab};
|
||||||
|
case KEY_RESIZE: return resize(m_dimensions);
|
||||||
|
}
|
||||||
|
|
||||||
if (c > 0 and c < 27)
|
if (c > 0 and c < 27)
|
||||||
{
|
{
|
||||||
if (c == control('m') or c == control('j'))
|
if (c == control('m') or c == control('j'))
|
||||||
|
@ -546,45 +563,6 @@ Optional<Key> NCursesUI::get_next_key()
|
||||||
}
|
}
|
||||||
return ctrl(Codepoint(c) - 1 + 'a');
|
return ctrl(Codepoint(c) - 1 + 'a');
|
||||||
}
|
}
|
||||||
else if (c == 27)
|
|
||||||
{
|
|
||||||
wtimeout(m_window, 0);
|
|
||||||
const Codepoint new_c = wgetch(m_window);
|
|
||||||
if (new_c == '[') // potential CSI
|
|
||||||
{
|
|
||||||
const Codepoint csi_val = wgetch(m_window);
|
|
||||||
switch (csi_val)
|
|
||||||
{
|
|
||||||
case 'I': return {Key::FocusIn};
|
|
||||||
case 'O': return {Key::FocusOut};
|
|
||||||
default: break; // nothing
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wtimeout(m_window, -1);
|
|
||||||
if (new_c != ERR)
|
|
||||||
{
|
|
||||||
if (new_c > 0 and new_c < 27)
|
|
||||||
return ctrlalt(Codepoint(new_c) - 1 + 'a');
|
|
||||||
return alt(new_c);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return {Key::Escape};
|
|
||||||
}
|
|
||||||
else switch (c)
|
|
||||||
{
|
|
||||||
case KEY_BACKSPACE: case 127: return {Key::Backspace};
|
|
||||||
case KEY_DC: return {Key::Delete};
|
|
||||||
case KEY_UP: return {Key::Up};
|
|
||||||
case KEY_DOWN: return {Key::Down};
|
|
||||||
case KEY_LEFT: return {Key::Left};
|
|
||||||
case KEY_RIGHT: return {Key::Right};
|
|
||||||
case KEY_PPAGE: return {Key::PageUp};
|
|
||||||
case KEY_NPAGE: return {Key::PageDown};
|
|
||||||
case KEY_HOME: return {Key::Home};
|
|
||||||
case KEY_END: return {Key::End};
|
|
||||||
case KEY_BTAB: return {Key::BackTab};
|
|
||||||
case KEY_RESIZE: return resize(m_dimensions);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < 12; ++i)
|
for (int i = 0; i < 12; ++i)
|
||||||
{
|
{
|
||||||
|
@ -608,7 +586,30 @@ Optional<Key> NCursesUI::get_next_key()
|
||||||
return Key{utf8::codepoint(getch_iterator{m_window},
|
return Key{utf8::codepoint(getch_iterator{m_window},
|
||||||
getch_iterator{m_window})};
|
getch_iterator{m_window})};
|
||||||
}
|
}
|
||||||
return {};
|
};
|
||||||
|
|
||||||
|
if (c == 27)
|
||||||
|
{
|
||||||
|
wtimeout(m_window, 0);
|
||||||
|
const int new_c = wgetch(m_window);
|
||||||
|
if (new_c == '[') // potential CSI
|
||||||
|
{
|
||||||
|
const Codepoint csi_val = wgetch(m_window);
|
||||||
|
switch (csi_val)
|
||||||
|
{
|
||||||
|
case 'I': return {Key::FocusIn};
|
||||||
|
case 'O': return {Key::FocusOut};
|
||||||
|
default: break; // nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
wtimeout(m_window, -1);
|
||||||
|
|
||||||
|
if (auto key = parse_key(new_c))
|
||||||
|
return alt(*key);
|
||||||
|
else
|
||||||
|
return {Key::Escape};
|
||||||
|
}
|
||||||
|
return parse_key(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
Loading…
Reference in New Issue
Block a user