我正在用 C++ 编写 readline 替换,我想以原始模式处理终端输入,包括特殊/转义键,如 "up arrow" \e[A
。但是,我还希望能够区分单次按下 Escape 键\e
,然后按下[
和按下A
与按下向上箭头。
我认为这两种情况之间的主要区别在于,当按下向上箭头时,输入字符会在不到一毫秒的时间内输入,所以我想我可以这样做:
#include <termios.h>
#include <absl/strings/escaping.h>
#include <iostream>
termios enter_raw() {
termios orig;
termios raw;
tcgetattr(STDOUT_FILENO, &orig);
tcgetattr(STDOUT_FILENO, &raw);
raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON);
raw.c_oflag &= ~OPOST;
raw.c_cflag |= CS8;
raw.c_lflag &= ~(ECHO | ICANON | IEXTEN | ISIG);
raw.c_cc[VMIN] = 1;
raw.c_cc[VTIME] = 0;
tcsetattr(STDOUT_FILENO, TCSAFLUSH, &raw);
return orig;
}
int main() {
termios orig = enter_raw();
while(true) {
char buf[10];
memset(buf, 0, sizeof(buf));
std::cin >> buf[0];
usleep(1000);
int actual = std::cin.readsome(buf + 1, sizeof(buf) - 2);
std::cout << "Got string: \"" << absl::CEscape(buf) << "\"\n";
if(buf[0] == 35) { break; } // received ctrl-c
}
tcsetattr(STDOUT_FILENO, TCSAFLUSH, &orig);
return 0;
}
但是,这个输出并不Got string: "\033[A"
像我希望的那样;相反,它做Got string
了三遍,就像它只是一个简单的字符循环一样。改变它休眠的微秒数似乎不会影响任何事情。
有没有办法在 C++ 中轻松实现这种东西?它可以移植到大多数终端吗?我不在乎支持Windows。答案不必使用<iostream>
;只要能完成工作,它就可以使用 C 风格的终端 IO。