我正在用C#构建一个telnet应用程序(用于在oldschool BBS系统上编写门游戏,例如Wildcat),似乎无法为ANSI转义码构建一个有效的解析器(例如光标移动,着色等) - 几乎所有我测试过的系统发送了未定义的序列,这些序列违反了任何“标准”。关于此事的资源似乎也很少,Wikipedia has the most in-depth list I've found so far但即使他们说它不完整 - 我遇到的大多数其他网站只是复制/粘贴了维基百科的文章。
我的问题:那里有图书馆吗?如果没有,一些解析代码/正则表达式怎么样?至少对ESC[!_
之类的一些适当的文档会非常有帮助。
我真的觉得我正在重新发明这一点,特别是看到Telnet或多或少是互联网相当于轮子(至少在年龄方面;)
编辑:添加了一个奇怪的例子:
00000075h: 1B 5B 73 1B 5B 32 35 35 42 1B 5B 32 35 35 43 08 ; .[s.[255B.[255C.
00000085h: 5F 1B 5B 36 6E 1B 5B 75 1B 5B 21 5F 02 02 3F 48 ; _.[6n.[u.[!_..?H
00000095h: 54 4D 4C 3F 1B 5B 30 6D 5F 1B 5B 32 4A 1B 5B 48 ; TML?.[0m_.[2J.[H
000000a5h: 0C 0D 0A ; ...
The mysterious part is '21' in line 2 ---^^
答案 0 :(得分:4)
正确的答案取决于打算如何使用该库。任何终端仿真器都将读取这些序列,并基于它们执行操作。但即使是一个简单的终端模拟器也能理解大约一百个序列。
您的示例,可能更具可读性,如下所示:
\E[s \E[255B \E[255C\t_ \E[6n \E[u \E[!_^B^B?HTML? \E[0m_ \E[2J \E[H\f\r \n
使用unmap
(使转义字符\E
并显示所有字符可打印 - 并为转义字符开始一个新行。)
ECMA-48描述了
的格式控制序列的内容(参数)仅限于某些字符,如数字和分隔符,例如';'
。控制序列也有一个明确的结局,称为 final 字符。序列\E[!_^B^B?
不符合这些规则。正如评论中所建议的那样,终端对光标位置请求\E[6n
的响应可能会使您的录音混淆。
有这么多背景:
\E[2J
清除显示)\E[6n
询问终端光标 的位置)\E[s
和\E[u
保存光标位置并稍后恢复)简而言之,您可能会看到为了处理终端收到的控制序列,您确实需要一个终端程序来完成所有这些操作。但是,并非所有终端仿真器都是相同的。有些使用一系列case语句来处理转义,括号,数字等的连续阶段。但是你的程序应该记住,单字节控件可以出现在多字节控制序列的中间。由于它们的编码方式不同,因此没有冲突。但它使程序比你想象的一次只读一个序列更复杂。
xterm使用一些case语句(基本上用于 final 字符),但解码控制序列的大多数状态转换都是使用一组表完成的。它们非常重复,但构造起来并不明显:Paul Williams指出,对于VT100,它们应该是对称的(基本上将输入视为7位ASCII)。某些州被视为错误,被忽略;格式良好的序列无论如何都是重要的。理论上,您可以重用状态表并添加“小”解析。表格为8500行(每行一个州)。
除了(a)阅读现有的终端仿真器并以较小的规模模仿它们,或(b)修改终端仿真器......你可以调查libvterm
:
一个抽象的C99库,它实现了一个VT220或类似xterm的终端模拟器。它不使用任何特定的图形工具包或输出系统,而是调用其嵌入程序应该提供它代表它绘制的回调函数指针。它避免了在正常运行状态下调用malloc(),允许它在嵌入式内核情况下使用。
但是,这不在C#
中(源是文档)。不过,它只有5500行代码。
进一步阅读: