Как использовать ввод, одновременно перехватывая нажатия стрелок (C++, Linux)
Я пишу CLI программу и при нажатии стрелок вверх/вниз должна прокручиваться история команд. Но есть проблема: при использовнии std::getline
и std::cin
невозможно перехватить их нажатие. Единственное, до чего я додумался, это реализовать цикл с функцией getchar
, но получается относительно раздутый код:
constexpr int ENTER_KEY_CODE = 10;
constexpr int ARROW_KEY_CODE_SEQUENCE_1 = 27;
constexpr int ARROW_KEY_CODE_SEQUENCE_2 = 91;
constexpr int UP_ARROW_KEY_CODE = 65;
constexpr int DOWN_ARROW_KEY_CODE = 66;
constexpr int BACKSPACE_KEY_CODE = 127;
static std::string read() noexcept
{
std::string input;
int inputCode = 0;
while (inputCode != ENTER_KEY_CODE)
{
inputCode = getchar();
switch (inputCode)
{
case ARROW_KEY_CODE_SEQUENCE_1:
if (getchar() == ARROW_KEY_CODE_SEQUENCE_2)
{
switch (getchar())
{
case UP_ARROW_KEY_CODE:
/* ... */
break;
case DOWN_ARROW_KEY_CODE:
/* ... */
break;
}
}
break;
case ENTER_KEY_CODE:
/* ... */
break;
case BACKSPACE_KEY_CODE:
/* ... */
break;
default:
/* ... */
break;
}
}
return std::move(input);
}
Как перехватить нажатие стрелок при вводе? Только без (n)curses.
Ответы (1 шт):
Да, я думал в верном направлении: без (n)curses всё делается вручную вместе с перехватом нажатий на Backspace, Enter и т.д. Вот как это примерно выглядит:
constexpr int ENTER_KEY_CODE = 10;
constexpr int ARROW_KEY_CODE_SEQUENCE_1 = 27;
constexpr int ARROW_KEY_CODE_SEQUENCE_2 = 91;
constexpr int UP_ARROW_KEY_CODE = 65;
constexpr int DOWN_ARROW_KEY_CODE = 66;
constexpr int BACKSPACE_KEY_CODE = 127;
static std::string read() noexcept
{
std::string input;
int inputCode = 0;
while (inputCode != ENTER_KEY_CODE)
{
inputCode = getchar();
switch (inputCode)
{
case ARROW_KEY_CODE_SEQUENCE_1:
if (getchar() == ARROW_KEY_CODE_SEQUENCE_2)
{
switch (getchar())
{
case UP_ARROW_KEY_CODE:
/* ... */
break;
case DOWN_ARROW_KEY_CODE:
/* ... */
break;
}
}
break;
case ENTER_KEY_CODE:
std::cout << std::endl;
break;
case BACKSPACE_KEY_CODE:
input = std::move(input.substr(1, input.size()));
std::cout << "\b \b";
break;
default:
input += inputCode;
std::cout << (char)inputCode;
break;
}
}
return std::move(input);
}
Перехватывать исключения и тестировать код я пока не стану, это общая логика.
Update: Как подсказали в комментариях, можно использовать библиотеку GNU Readline, что тоже подойдет для решения данной проблемы.