我正在为*nix系统编写一个命令行应用程序。我想把stdin上的字节转换成输入设备事件,比如"左键点击"、"向上滚动轮滴答/运动"、"按下ctrl-alt-shift-Left-arrow"等等。
我非常高兴在过去的10-20年里,人们只做了99%的事情,也就是说,如果有人把一个物理VT100插入他们的机器,而我的应用程序在上面不起作用,我可以接受。然而,我希望充分利用xterm和朋友们的功能,并且我希望尽可能了解stdin上的字节是什么意思。
如何做到这一点?换句话说,我如何非常近似地重新实现ncurses的输入子系统?
据我所知,几乎所有终端上的转义键表示都是大多数(例如箭头和函数键转义序列(的前缀,而非前缀的编码是出了名的难以消除歧义,尤其是当M-x的编码方式与ESC后跟x时;-(
到目前为止,这个小问题已经被提升为命令行ui约定,尽管如此,但更令人担忧的是:假设我想建立一个已知转义序列的数据库(以及从上下文(例如$TERM
值(到数据库切片的映射(,如果我的程序接收到未知的输入序列,我会跳过它。我如何判断转义序列的结束位置?据我所知,这并不容易实现。我想要命令的单字符热键,但我不希望未知的转义序列触发它们。
据我所知,这几乎是不可能的。
我最好的想法是凭经验进行:建立一个我所知道的所有终端模拟器的列表,向每个模拟器提供所有有效的X11密钥输入,看看另一端会出现什么。在某种程度上,终端模拟器可以在X键到十二字节的映射中进行配置,这将非常棘手。但就我所能理解的世界而言,这大致就是terminfo
terminfo(和termcap(为应用程序提供了一个已知密钥代码的字典。但是这些字典的大小是有限的。一些终端(仿真器(可以提供比termcap(1024字节(或terminfo(传统格式中的4096字节——也许ncurses中当前的65536字节就足够了(中定义的多得多的内容。
任何所谓的";现代的";终端将遵循这样的约定,即键(输入(绑定到与ECMA-48(仅寻址输出的(相对应的东西。这在一定程度上是因为可以在终端的本地模式中解释的键(尤其是光标键(。
很可能,给定的终端模拟器不实现本地模式(ECMA-48SRM
(,但xterm实现了。因为(兼容性和缺乏创新的结合(其他终端开发人员都遵循这种模式。这并不是密钥编码的唯一方式(例如,错误命名的ANSI.SYS,其使用空字符的方案是由少数"现代"开发人员"发明"的(。
curses/termcap应用程序依赖于这个字典,而不需要对密钥编码的格式进行假设。但是,如果有人(通过修改curses库或curses/termcap应用程序(选择将任何未知的字节序列视为KEY_UNKNOWN
,如果它遵循ECMA-48模式,那么这将简化应用程序中的恢复。