Можно ли использовать Terminal.app для соблюдения кодов выхода ANSI?

Я замечаю, что с переменной окружения TERM, установленной как xterm или xterm-256color, что утилита Mac OS Xs Terminal.app соответствует большинству кодов выхода ANSI, как минимум, когда эти escape-коды относятся к изменению цвета текста.

Например:

echo -e "\033[0;31mERROR:\033[0m It worked"

Выдает:

Снимок экрана

Тем не менее, Im больше интересовался функциональностью манипулирования местоположением курсора, предоставляемой escape-кодами ANSI. К сожалению, этот тип кода не работает слишком хорошо в Terminal.app, из того, что Ive удалось собрать. Например, я хочу сделать что-то вроде этого:

echo -e "\033[sHello world\033[uG'day"

ESC[s Сохраняет текущую позицию курсора, тогда как ESC[u восстанавливает последнюю сохраненную позицию. В результате выполнения script выше Id ожидает, что пять символов в "G'day" перечеркнут пять символов "Hello" после того, как курсор был перемещен, создавая следующее:

G'day world

В самом деле, это именно то, что я получаю с iTerm2.app, ConEmu для Windows (выполняется либо MinGW, либо MSYS Git с копией bash.exe) и т.д. То, что я вижу в Terminal.app, это:

Hello worldG'day

Есть ли причина для этого, кроме того, что Terminal.app просто не поддерживает эти коды? Есть ли способ включить эту функциональность? Есть ли шанс, что у меня что-то неправильно сконфигурировано? Моя настройка TERM? Что-то еще?

Ive искал везде, но havent нашел что-то относящееся к Terminal.app, в частности. Мне показалось странным, что он будет поддерживать цветной текст через escape-коды ANSI, но не переместить курсор по той же технологии. Это похоже на довольно произвольное подмножество довольно четко определенного стандарта. То, что заставляет меня думать, что у меня что-то неправильно сконфигурировано, а не на том, что Terminal.app - это тот, кто виноват... но, я полагаю, его возможно, что это просто невозможно сделать. (Вероятно, одна из причин, по которой iTerm2 существует в первую очередь?)

Если кто-то может пролить свет на эту ситуацию, то очень ценю!

UPDATE

Итак, я немного побольше читал и экспериментировал, и обнаружил следующую странность:

Посмотрите на n.m. ответ ниже, я решил записать байты, возвращаемые tput в файл, чтобы посмотреть, как они отличаются от обычной инструкции ANSI.

$ echo "$(tput sc)Hello world$(tput rc)G'day" > out.bin
$ cat -e out.bin
^[7Hello world^[8G'day$

Кажется, что все работает так, как ожидалось, если я отправлю ему последовательности ESC 7 и ESC 8, но НЕ, если я отправлю его ESC [s и ESC [u, что, как я понимаю, является более типичным представлением кодов ANSI SCP и RCP (соответственно сохранить положение курсора и положение курсора). Так как поместить десятичные символы ASCII 7 или 8 рядом с эскизным восьмеричным представлением байта невозможно (\0337!= ESC), вместо этого вместо этого можно использовать переменные окружения, чтобы не полагаться на tput:

$ esc=$'\033'
$ csi="${esc}["
$ echo "${csi}0;31mERROR:${csi}0m It worked."
ERROR: It worked.  # Color works, as before
$ echo "${csi}sHello world${csi}uG'day"
Hello worldG'day   # No dice
$ echo "${esc}7Hello world${esc}8G'day"
G'day world        # Success

Я не уверен, почему это так. Если ESC 7 и ESC 8 являются своего рода проприетарным или настраиваемым кодом для ANSI SCP и RCP, который может варьироваться от терминальной реализации до реализации терминала, это объясняет мне, почему tput был созданный в первую очередь.

К сожалению, я не могу использовать tput для того, над чем я сейчас работаю, поскольку я не работаю исключительно в среде bash. Мне более любопытно, как интерпретируются необработанные байты с терминала на терминал и, более конкретно, , есть ли способ заставить Terminal.app соблюдать одни и те же escape-коды ANSI, что и все остальные эмуляторы терминала я Кажется, у нас не было проблем. Возможно ли это?. В этот момент я начинаю думать, что это просто не может быть, что хорошо, но было бы хорошо знать наверняка и, возможно, также узнать причину.

Ответы

Ответ 1

Не используйте коды ANSI. Используйте правильные методы на основе terminfo. Терминалы на основе Xterm не указаны для поддержки всех кодов ANSI. Некоторые делают для совместимости, некоторые - нет.

Сохранение позиции курсора задается командой tput sc, а позиция курсора восстановления tput rc.

echo -e "$(tput sc)Hello world$(tput rc)G'day"

должен работать на любом терминале, который поддерживает эти последовательности.

Чтобы увидеть читаемое представление поддерживаемых последовательностей, используйте команду infocmp. Выходной сигнал может быть довольно длинным. Если вас интересуют sc и rc:

infocmp | grep --color ' [sr]c='

Отказ от ответственности: протестирован на моей машине Linux, у вас нет Mac.

UPDATE

Terminal.app моделируется после xterm, а xterm моделируется после терминала VT100. VT100 не реализовывал последовательности CSI u и CSI s, но использовал DEC private ESC 7 и ESC 8 последовательности (источник). Позже модели VT поддерживали как CSI s/u, так и ESC 7/8 под другим именем и с немного отличающимися функциональными возможностями (источник).

ECMA 48, похоже, не указывает никаких последовательностей позиции курсора сохранения/восстановления (источник (PDF)), или я не смог найти их там. Я не знаю, откуда CSU s/u. Их имя в документации VT510 предполагает, что они каким-то образом связаны с ШОС. Этот источник предполагает, что они на самом деле являются частными последовательностями без стандартного значения. Терминалы SUN используют SCI s для выполнения reset. Вероятно, это ошибка для маркировки этих двух последовательностей ANSI.

Современные версии xterm и других терминальных программ X11 (konsole, rxvt...) поддерживают как ESC 7/8, так и CSI s/u, но база данных terminfo рекламирует только ESC 7/8. Terminal.app, по-видимому, поддерживает только ESC 7/8.