0

我正在编写一个 CLI 服务器。在我的项目中,我执行以下操作(简化):

curses.setupterm("rxvt")
smkx = curses.tigetstr("smkx")
write_to_terminal_client(smkx)

检测到的 smkx 序列只有与“infocmp rxvt”匹配的“\E=”(一个糟糕的 terminfo 条目?)。

现在,当我运行我的 CLI 服务器并在 rxvt 终端上运行 telnet 连接到它时,终端会收到 smkx 序列。当 rxvt 终端上的用户按下左箭头键时,我希望将“\E[D”序列发送到 CLI 服务器(因为已设置应用程序模式)。不幸的是,当 smkx 序列已发送和未发送到终端客户端时,序列始终为“\EOD”。

我尝试将 smkx 序列硬编码为 "\E[?1h\E=" 并将其发送给客户端,但它没有改变任何东西。

终端也不响应 DECRQM 查询。

我的全貌是我的应用程序学习终端的名称并查询 terminfo 数据库以获取关键代码和其他功能。我正在运行 ubuntu 13.10。Rxvt 终端是“2.7.10”

问题:

  1. 我做错什么了吗?
  2. 如果不是,我应该如何理解 smkx="\E=" 而不是 "\E[?1h\E=" (不支持 DECCKM?)
  3. 如何正确检测此类情况并处理它们(回退到 ANSI 游标序列?)

问候

4

1 回答 1

1

问题似乎是您的程序正在发送smkx(好),但假设它知道将为各种特殊键发送的字符串(不好)。在正确构造的终端描述中,还列出了特殊键(请参阅terminfo(5)):

  key_up                    kcuu1  ku   up-arrow key
  key_down                  kcud1  kd   down-arrow key
  key_left                  kcub1  kl   left-arrow key
  key_right                 kcuf1  kr   right-arrow key

\E[D因此,您的程序应该寻找tigetstr字符串为的任何内容,而不是寻找kcub1

关于DECRQM, rxvt 可能无法实现,因为它不是“VT100”控制序列。参考XTerm Control Sequences,即“For VT300 and up”,而rxvt 的手册页说“vt102 终端”。

虽然偶尔会报告一些问题,但终端数据库在很大程度上反映了用户约定和实际终端功能之间的权衡。一些用户(尤其是 Linux 用户bash)不喜欢使用终端的应用模式。在这个利基之外,长期的惯例是使用应用程序模式。xterm 手册提供了关于这个主题的更多讨论。

在 ncurses 中,该infocmp命令具有一个功能(选项-i),可以让您(更)清楚地看到初始化字符串的效果。它不会分解 rmkx/smkx,但很容易添加。这样做,它将报告 rxvt:

is1: {DEC-47}{DECPAM}{DEC-CKM}
is2: {RSR}{SGR0}\E[2J{home}{DEC+AWM}{DEC-CKM;COLM;SCLM;OM}{rmir}
rs1: {rmkx}{ECMA-1;3;IRM;5;6}{DEC+AWM}{SGR0}{RSR}\E[2J{home}
rs2: {is2}{rmkx}{DEC-1000}{cnorm}
smcup: {sc}{DEC+47}
rmcup: \E[2J{DEC-47}{rc}
smkx: {DECPAM}
rmkx: {DECPNM}

和 xterm:

is2: \E[!p{DEC-COLM;SCLM}{rmir}{DECPNM}
rs1: {RIS}
rs2: {is2}
smcup: {DEC+1049}
rmcup: {DEC-1049}
smkx: {DEC+CKM}{DECPAM}
rmkx: {DEC-CKM}{DECPNM}

也就是说,xterm 的终端描述DECCKM使用 smkx/rmkx 打开/关闭(光标键),而 rxvt 的终端描述则没有。此外,rxvt 的初始化字符串DECCKM关闭。

于 2015-05-19T08:36:20.733 回答