我正在尝试使用
ncurses
构建一个简单的终端程序,但我很难尝试读取 (Ctrl+shift+) 或 (Ctrl+) 等组合键
我尝试了其他库,例如
libtickit
,它可以在桌面终端中读取这些组合,但在仅 TTY 中效果不佳(我使用的是 Linux)。
我看到nano使用ncurses,他们支持这种组合(如Ctrl+shift+箭头),但代码非常复杂。
有人知道一种方法或任何其他库(甚至是其他语言)可以检测大多数现代 UNIX 终端的这个组合键吗?
谢谢。
首先,不存在“简单”终端程序。对不起。
某些修饰符+按键组合可以很好地检测到,但不是全部,也不是给定修饰符集的所有键。
您可以在 *nixen 和 Windows 上执行此操作!但我们将根据您的问题标签重点关注 *nixen(包括 WSL)。
例如,只需按 Ctrl+A 即可获得
^A
,其键码值为 1
。同样,Ctrl+B 可以获取 2
的键值。 (在 C 语言中,您可以将它们写为 '\1'
和 '\2'
。)
这些是您的标准“控制代码”。并非键盘上的每个键都会产生控制代码,有些键不需要 Ctrl
键即可产生控制代码,例如 Return
和 Backspace
。
大多数带有 Alt 键的东西只是以 Esc 键代码 (27) 为前缀的键代码。同样,并非每个键都可以成功地与 Alt 组合使用。
同样,Shift的效果取决于按键。除了特殊功能(如箭头键)之外,它仅适用于字母数字键(切换其状态 - 大写锁定也必须被跟踪!就像,WT--?!)
幸运的是,按 Ctrl+Shift+左箭头 会产生一个简短的、可识别的转义序列(具体为:Esc;6D)。那里的
6
是识别按下哪个修饰键的关键:减去 1,设置的位就是您的修饰键代码:
一点 | 2 | 1 | 0 |
---|---|---|---|
修饰符 | Ctrl | 替代 | 移动 |
不过,使用 Curses 时你不会得到这样的结果。如果您使用 Curses,您可以使用
keyname()
函数 (man 3NCURSES util) 获取“键名称”。对于Ctrl+Shift+左箭头,按键名称是...“kLFT6
”!非常方便!
这表明您应该使用查找表来确定是否输入了特定(修饰符+箭头键)组合,而不是尝试单独选择它们。
不要太担心如何提高字符串和其他东西的效率。即使使用字符串查找,它也会在用户的手指离开按键之前完成。
让这一切变得更加复杂的是“meta”键的历史使用,它莫名其妙地映射到Esc键,使得计时成为一个问题。换句话说,读取关键响应序列时必须特别小心。确保将初始化代码添加到您的程序中,以将
esc_delay()
设置为相当小的值:
int DEFAULT_ESC_DELAY = 100; // 50..150 ms are reasonable values,
// assuming you are using a local terminal. If user is using dialup/
// network terminal, he/she should have ESCDELAY set in the environment
// anyway!
int get_esc_delay_value(void)
{
const char * s = getenv( "ESCDELAY" );
if (!s) return DEFAULT_ESC_DELAY;
errno = 0;
char * end;
long n = strtol( s, &end, 0 );
if ((s == end) or (errno) or (*end)) return DEFAULT_ESC_DELAY;
if (n < 0) return 0;
if (n > 5000) return 5000; // 5 sec is insanely large, but...
return n;
}
...
esc_delay( get_esc_delay_value() );
最后,终端本身、操作系统甚至终端仿真器选项可能会施加一些限制!
例如,很可能 Ctrl+Shift+向上箭头 已被您的终端模拟器捕获,这意味着您的程序永远不会看到它。让用户弄清楚如何从他或她的 TE 中删除一个方便的快捷方式,你可以将其放入“太难计算”的桶中。
啊啊啊啊啊啊啊啊啊啊啊啊啊啊!