Парсинг кодов выхода ANSI?
Я создаю приложение telnet на C# (для сценариев дверных игр на старых системах BBS, например, в Wildcat) и не могу создать работающий синтаксический анализатор для управляющих кодов ANSI (например, перемещение курсора, раскраска и т. Д.) - почти для всех систем, которые я Мы протестировали отправку неопределенных последовательностей, которые не поддаются никаким "стандартам". Похоже, что ресурсов по этому вопросу очень мало, у Википедии самый полный список, который я нашел, но даже они говорят, что он неполон - и большинство других сайтов, с которыми я встречался, просто копируют / вставляют статью из Википедии.
Мой вопрос: есть ли там библиотека? Если нет, то как насчет кода разбора / регулярных выражений? По крайней мере, некоторая надлежащая документация для таких вещей, как 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 ---^^
1 ответ
Правильный ответ зависит от того, как вы собираетесь использовать библиотеку. Любой эмулятор терминала будет читать эти последовательности и выполнять действия на их основе. Но даже простой эмулятор терминала поймет около сотни последовательностей.
Ваш пример, возможно, в более читаемой форме, выглядит следующим образом:
\ E [s \ E [255B \ E [255C \ t_ \ E [6n \Евросоюз \E[!_^B^B?HTML? \E[0m_ \E[2J \ Е [Н \ х \ г \ п
с помощью unmap
(делая побег персонажа \E
и показ всех печатаемых символов - и начало новой строки для escape-символов).
ECMA-48 описывает формат для
- однобайтовые управляющие символы и
- многобайтовые управляющие последовательности (начиная с escape-символа).
Управляющие последовательности имеют содержание (параметры), которые ограничены определенными символами, такими как цифры и разделители, например, ';'
, Контрольные последовательности также имеют определенное окончание, называемое конечным символом. Последовательность \E[!_^B^B?
не следует этим правилам. Как предлагается в комментарии, возможно, ваша запись была смущена ответом терминала на запрос позиции курсора \E[6n
,
С таким большим контекстом:
- некоторые действия, выполняемые эмулятором терминала, изменяют отображение (
\E[2J
очищает дисплей) - некоторые действия, выполняемые эмулятором терминала, сообщают хосту об отображении (
\E[6n
спрашивает терминал, где находится курсор) - некоторые действия, выполняемые эмулятором терминала, изменяют поведение терминала (
\E[s
а также\E[u
сохранить положение курсора и восстановить его позже)
Короче говоря, вы можете видеть, что для обработки управляющих последовательностей, полученных терминалом, вам действительно нужна терминальная программа для всего этого. Однако не все терминальные эмуляторы одинаковы. Некоторые используют серию операторов case для обработки последовательных этапов escape, скобок, цифр и т. Д. Но ваша программа должна иметь в виду, что однобайтовые элементы управления могут появляться в середине многобайтовых последовательностей элементов управления. Поскольку они кодируются по-разному, конфликта нет. Но это делает программу более сложной, чем можно было бы предположить, читая только одну последовательность за раз.
xterm использует некоторые операторы case (в основном для последнего символа), но большинство переходов состояний при декодировании управляющей последовательности выполняется с использованием набора таблиц. Они очень повторяющиеся, но не очевидные для построения: Пол Уильямс указал, что для VT100 они должны быть симметричными (по сути, трактуя вход как 7-битный ASCII). Некоторые из состояний рассматриваются как ошибки и игнорируются; хорошо отформатированные последовательности - все, что имеет значение в любом случае. Теоретически, вы можете повторно использовать таблицы состояний и добавить "маленький" анализ. Таблицы состоят из 8500 строк (по одному состоянию на строку).
Помимо (а) чтения существующих эмуляторов терминала и имитации их в меньшем масштабе, или (б) изменения эмулятора терминала... вы можете исследовать libvterm
:
Абстрактная библиотека C99, которая реализует эмулятор терминала типа VT220 или xterm. Он не использует какой-либо конкретный графический инструментарий или систему вывода, вместо этого он вызывает указатели на функции обратного вызова, которые его программа встраивания должна предоставлять для рисования от его имени. Он избегает вызова malloc() во время нормального состояния работы, что позволяет использовать его во встроенных ситуациях ядра.
Однако это не в C#
(и источником является документация). Тем не менее, это всего лишь 5500 строк кода.
Дальнейшее чтение: