Windows Terminal, PowerShell: управляющие коды ANSI для управления цветами

Jul 11, 2022 13:55

Программы-«эмуляторы терминала» давным-давно (с 1970-х годов) умеют работать с так называемыми «управляющими последовательностями ANSI» (по-английски «ANSI escape codes» или «ANSI escape sequences»). Вернее, с ними так давно умеют работать программы-«эмуляторы терминала» в Unix-подобных операционных системах, а вот программы-«эмуляторы терминала» от компании «Microsoft» («Windows Console» и «Windows Terminal») научились это делать совсем недавно. Поэтому лично для меня эти управляющие последовательности в новинку, так как я всегда работал только в операционных системах «Windows» (сейчас работаю в операционной системе «Windows 10 Pro»).

Подробнее про эти управляющие последовательности:

https://en.wikipedia.org/wiki/ANSI_escape_code
https://ru.wikipedia.org/wiki/Управляющие_последовательности_ANSI

Как и для чего используются эти последовательности (коды)

Люди используют текстовый интерфейс (командную строку) уже довольно давно. Чтобы управлять форматом, цветом и другими опциями внешнего вида выводимого в консоль текста (например, для вывода результатов работы какой-нибудь программы), они придумали вставлять в выводимый текст специальные управляющие последовательности символов, которые программа-«эмулятор терминала» расшифровывает и оформляет выводимый текст так, как желает пользователь.

Меня сейчас интересует управление основным цветом и цветом фона для выводимого текста. Поэтому в этом посте речь пойдет именно об управляющих последовательностях для управления цветами.

Как это работает на практике

Я работаю с программой-«эмулятором терминала» «Windows Terminal», в которой запускаю программу-оболочку «PowerShell» версии 7. Чтобы дать этой программе-оболочке команду вывести определенный текст в консоль, достаточно набрать нужный текст, обособив его кавычками, и нажать клавишу «Enter»:

> "Мама мыла раму."



На вышеприведенной иллюстрации программа-«эмулятор терминала» «Windows Terminal» получила текст от программы-оболочки и отобразила его в окне консоли. При этом она использовала цвет фона и цвет текста по умолчанию. Значения по умолчанию указаны в настройках программы-«эмулятора терминала» «Windows Terminal», их можно изменить.

Запишем наш тестовый текст в файл «тест.txt» (в кодировке UTF-8, это одна из кодировок Юникода), чтобы в случае необходимости можно было открыть этот текст в двоичном редакторе (он же - «шестнадцатеричный редактор» или «hex-редактор»). Теперь выведем файл «тест.txt» (его размер - 27 байтов) в консоль и убедимся, что результат тот же самый, что и ранее:

> get-content "тест.txt"



Предположим, я хочу, чтобы программа-«эмулятор терминала» при выводе текста из вышеуказанного файла отобразила слово «мыла» на фоне другого цвета, а также я хочу, чтобы при этом цвет текста этого слова тоже отличался от цвета текста по умолчанию. Чтобы этого добиться, я добавлю в тестовый текст в файле управляющие коды. Новое содержимое файла, размер файла увеличился до 38 байтов:



Как видно на вышеприведенной иллюстрации, всё получилось так, как я планировал: программа-«эмулятор терминала» «Windows Terminal» отобразила слово «мыла» на другом фоне, а также цвет текста для этого слова тоже был изменен по сравнению с цветом текста по умолчанию.

Как я этого добился? Я добавил в файл «тест.txt» перед словом «мыла» следующую управляющую последовательность (код):

ESC[41;30m
В двоичном виде она состоит (на вышеприведенной иллюстрации подчеркнута красной линией в двоичном редакторе) из 8 байтов:

1B 5B 34 31 3B 33 30 6D

Тут следует иметь в виду, что сокращение ESC здесь - это условность, которая на самом деле обозначает байт 1B. В таблице Юникода это символ U+001B, он не имеет графического представления, поэтому его обозначают сокращением ESC. В текстовых редакторах этот символ обычно сложно ввести, так как текстовые редакторы предназначены для работы с видимыми символами (символами, имеющими графическое представление). Поэтому я ввел этот символ в двоичном редакторе.

Для изменения цвета фона и/или цвета текста управляющая последовательность (код) конструируется из открывающей части ESC[ и закрывающей части m, между которыми могут быть указаны одно или несколько чисел (числа могут и вообще не указываться). Если чисел несколько, они разделяются символом ; (точка с запятой).

В данном случае в управляющей последовательности указано два числа - 41 и 30. Порядок их указания не имеет значения, то есть в данном случае в укправляющей последовательности их можно поменять местами, результат не изменится. Число «41» указывает нужный цвет фона, а число «30» указывает нужный цвет текста. Я в этом посте не хочу останавливаться на том, что конкретно значат именно эти числа (я думаю написать об этом отдельный пост). В этом посте главное понять, как работают управляющие последовательности в общем, и что они собой представляют.

Если вставить только управляющую последовательность ESC[41;30m перед словом «мыла», то данное действие изменит цвета фона и текста, начиная со слова «мыла» и для любого текста, выводимого в консоль далее. Мне же хотелось выделить только слово «мыла». Поэтому после слова «мыла» я вставил еще одну управляющую последовательность, которая сбросила настройки цветов к цветам по умолчанию.

Эта управляющая последовательность следующая:

ESC[m
В двоичном виде она состоит (на вышеприведенной иллюстрации тоже подчеркнута красной линией в двоичном редакторе) из 3 байтов:

1B 5B 6D

Эта управляющая последовательность состоит только из открывающей и закрывающей частей, между которыми не указано никаких чисел. Управляющая последовательность ESC[m является синонимом управляющей последовательности ESC[0m (можно было указать эту управляющую последовательность для сброса настроек цветов к цветам по умолчанию).

В скриптовом языке программы-оболочки «PowerShell»

Как было показано выше, программа-«эмулятор терминала» «Windows Terminal» (также как и программа «Windows Console» свежих версий) в операционной системе «Windows 10» умеет работать с управляющими последовательностями (кодами) ANSI. Это значит, что с управляющими кодами ANSI можно работать из любых программ-оболочек, работающих в указанных программах-«эмуляторах терминала».

Вернемся к самому первому практическому примеру, указанному в начале этого поста. Что делать, если нужно ввести управляющую последовательность не в текст, хранящийся в файле, а прямо в скрипт, запускаемый из программы-оболочки «PowerShell»? Как я уже упоминал ранее, ввести символ U+001B напрямую в программе-оболочке (как и в текстовом редакторе) сложно, это же не двоичный редактор. Вот один из способов это сделать в скриптовом языке программы-оболочки «PowerShell»:

> "Мама $([char]27)[41;30mмыла$([char]27)[m раму."



Тут для ввода символа U+001B используется конструкция скриптового языка $([char]27). Число «27» - это представление в десятичной системе счисления числа «1B» (в шестнадцатеричной системе счисления). Для понимания этой конструкции можно обратиться к статье «Об операторах» документации скриптового языка программы-оболочки «PowerShell».

Вышеизложенный способ работает как в программе «Windows PowerShell» (версия 5.1), так и в программе «PowerShell» (версии 6 и 7). Но разработчики посчитали, что имеет смысл обеспечить еще парочку способов, которые изложены ниже (нижеизложенные способы не работают в программе «Windows PowerShell» (версия 5.1), потому что были реализованы только в программе «PowerShell», начиная с версии 6).

> "Мама `e[41;30mмыла`e[m раму."
и

> "Мама `u{1B}[41;30mмыла`u{1B}[m раму."



В этих двух способах для ввода символа U+001B используются конструкции `e и `u{1B} соответственно. Об этом можно почитать статью «О специальных символах» документации скриптового языка программы-оболочки «PowerShell».

Инструмент, Образование, Программирование, Английский язык

Previous post Next post
Up