Последовательности виртуального терминала в консоли

Последовательности виртуальных терминалов — это последовательности символов управления, которые могут управлять перемещением курсора, цветом консоли и другими операциями при записи в выходной поток. Последовательности можно также получить из входного потока в ответ на последовательность сведений запроса потока вывода или в виде кодировки входных данных пользователя (если установлен соответствующий режим).

Для настройки такого поведения можно использовать функции GetConsoleMode и SetConsoleMode. В конце этого документа приведен пример предлагаемого способа включения поведения виртуальных терминалов.

Поведение следующих последовательностей основано на VT100 и производных технологиях эмулятора терминала, в частности эмулятора терминала xterm. Дополнительные сведения о последовательностях терминала можно найти по адресу http://vt100.net и http://invisible-island.net/xterm/ctlseqs/ctlseqs.html.

Выходные последовательности

Следующие последовательности терминалов перехватываются узлом консоли при записи в выходной поток, если флаг ENABLE_VIRTUAL_TERMINAL_PROCESSING установлен в дескриптор буфера экрана с помощью функции SetConsoleMode. Обратите внимание, что флаг DISABLE_NEWLINE_AUTO_RETURN также может оказаться полезным для эмулирования расположения курсора и прокрутки других эмуляторов терминала в отношении символов, записанных в последний столбец в любой строке.

Простое позиционирование курсора

Во всех следующих описаниях ESC всегда имеет шестнадцатеричное значение 0x1B. В последовательностях терминала не должно быть пробелов. Отдельные последовательности терминалов могут быть разделены по любому символу или байтам по нескольким последовательным вызовам WriteFile или WriteConsole, но рекомендуется включить всю последовательность в один вызов. Чтобы узнать, как использовать эти последовательности на практике, ознакомьтесь с примером в конце этой статьи.

В следующей таблице описаны простые escape-последовательности с одной командой действия непосредственно после символа ESC. Эти последовательности не имеют параметров и вступают в силу немедленно.

Все команды в этой таблице обычно эквивалентны вызову API консоли SetConsoleCursorPosition для размещения курсора.

Перемещение курсора будет ограничено текущим окном просмотра в буфере. Прокрутка (если доступна) не будет выполняться.

Sequence Сокращение Поведение
ESC M RI Обратный индекс — выполняет обратную операцию \n, перемещает курсор вверх по одной строке, сохраняет горизонтальное положение, буфер прокрутки при необходимости*
ESC 7 DECSC Сохранение позиции курсора в памяти**
ESC 8 DECSR Восстановление позиции курсора из памяти**

Примечание.

* Если есть поля прокрутки, ri внутри полей прокрутит только содержимое полей и оставьте окно просмотра без изменений. (См. раздел "Поля прокрутки".)

**Нет значения, сохраненного в памяти, пока не будет выполнено первое использование команды сохранения. Единственный способ получить доступ к сохраненному значению — выполнить команду восстановления.

Позиционирование курсора

В указанных ниже таблицах приведены последовательности типа CSI (начала управляющей последовательности). Все последовательности CSI начинаются с ESC (0x1B), за которым следует [ (левая скобка, 0x5B) и могут содержать параметры переменной длины, чтобы указать дополнительные сведения для каждой операции. Это будет представлено в виде сокращения <n>. Каждая таблица ниже сгруппирована по функциональности. Ниже таблицы указаны примечания, объясняющие, как работает эта группа.

Для всех параметров применяются следующие правила, если не указано иное:

  • <n> представляет расстояние для перемещения и является необязательным параметром;
  • если параметр <n> опущен или равен 0, он будет рассматриваться как 1;
  • <n> не может превышать 32 767 (максимальное короткое значение);
  • <n> не может быть отрицательным.

Все команды в этом разделе обычно эквивалентны вызову API консоли SetConsoleCursorPosition.

Перемещение курсора будет ограничено текущим окном просмотра в буфере. Прокрутка (если доступна) не будет выполняться.

Sequence Код Описание Поведение
ESC [ <n> A CUU Перемещение курсора вверх Перемещение курсора вверх на <n> позиций
ESC [ <n> B CUD Перемещение курсора вниз Перемещение курсора вниз на <n> позиций
ESC [ <n> C CUF Перемещение курсора вперед Перемещение курсора вперед (вправо) на <n> позиций
ESC [ <n> D CUB Перемещение курсора назад Перемещение курсора назад (влево) на <n> позиций
ESC [ <n> E CNL Перемещение курсора на следующую строку Перемещение курсора вниз на <n> строк от текущей позиции
ESC [ <n> F CPL Перемещение курсора на предыдущую строку Перемещение курсора вверх на <n> строк от текущей позиции
ESC [ <n> G CHA Перемещение курсора по горизонтали (абсолютное позиционирование) Курсор перемещается на <n>-ю позицию по горизонтали в текущей строке
ESC [ <n> d VPA Вертикальное положение строки (абсолютное позиционирование) Курсор перемещается на <n>-ю позицию по вертикали в текущем столбце
ESC [ <y> ; <x> H CUP Позиция курсора *Курсор перемещается на <x>; <Координата y в области просмотра, где <x> — столбец <строки y>>
ESC [ <y>; <x f> HVP Горизонтально-вертикальная позиция *Курсор перемещается на <x>; <Координата y в области просмотра, где <x> — столбец <строки y>>
ESC [ s ANSISYSSC Сохранение курсора — эмуляция Ansi.sys **Без параметров выполняет операцию сохранения курсора, например DECSC
ESC [ u ANSISYSRC Восстановление позиции курсора — эмуляция Ansi.sys **Без параметров выполняет операцию курсора восстановления, например DECRC

Примечание.

*<X> и y> имеют те же ограничения, что <и <n> выше. Если параметры <x> и <y> не указаны, им будут присвоены значения 1;1.

**ANSI.sys историческую документацию можно найти https://msdn.microsoft.com/library/cc722862.aspx и реализовать для удобства и совместимости.

Видимость курсора

Следующие команды управляют видимостью курсора и его мигающим состоянием. Последовательности DECTCEM обычно эквивалентны вызову API консоли SetConsoleCursorInfo для переключения видимости курсора.

Sequence Код Описание Поведение
ESC [ ? 12 h ATT160 Текстовый курсор: включение мигания Запуск мигания курсора
ESC [ ? 12 l ATT160 Текстовый курсор: отключение мигания Остановка мигания курсора
ESC [ ? 25 h DECTCEM Текстовый курсор: включение режима отображения Отображение курсора
ESC [ ? 25 l DECTCEM Текстовый курсор: включение скрытого режима Скрытие курсора

Совет

Последовательности включения заканчиваются символом строчной буквы H (h), а последовательности отключения — символом L (l).

Фигура курсора

Следующие команды управляют и позволяют настраивать фигуру курсора.

Sequence Код Описание Поведение
ESC [ 0 SP q DECSCUSR Фигура пользователя Фигура курсора по умолчанию, настроенная пользователем
ESC [ 1 SP q DECSCUSR Блок мигания Фигура курсора блока мигания
ESC [ 2 SP q DECSCUSR Устойчивый блок Устойчивая фигура курсора блока
ESC [ 3 SP q DECSCUSR Подчеркивание мигания Фигура курсора подчеркивания мигания
ESC [ 4 SP q DECSCUSR Устойчивое подчеркивание Фигура курсора устойчивого подчеркивания
ESC [ 5 SP q DECSCUSR Мигающий бар Фигура курсора индикатора мигания
ESC [ 6 SP q DECSCUSR Устойчивый бар Фигура курсора устойчивой панели

Примечание.

SP — символ пробела литерала (0x20) в промежуточной позиции, за которым следует q (0x71) в конечной позиции.

Позиционирование окна просмотра

Все команды в этом разделе обычно эквивалентны вызову API консоли ScrollConsoleScreenBuffer для перемещения содержимого буфера консоли.

Внимание! Имена команд недостоверны. Прокрутка — это направление, в котором текст перемещается во время операции, а не возможное направление перемещения окна просмотра.

Sequence Код Описание Поведение
ESC [ <n> S SU Прокрутка вверх Прокрутка текста вверх на <n> позиций. Это действие также называется сдвигом вниз, новые строки появляются в нижней части экрана.
ESC [ <n> T SD Прокрутите вниз Прокрутка вниз на <n> позиций. Это действие также называется сдвигом вверх, новые строки появляются в верхней части экрана.

Текст перемещается, начиная со строки, в которой расположен курсор. Если курсор находится в средней строке окна просмотра, то прокрутка вверх приведет к перемещению нижней половины окна просмотра и вставке пустых строк в нижней части. Прокрутка вниз приведет к перемещению верхней половины строк окна просмотра и вставке новых строк в верхней части.

Кроме того, обратите внимание, что прокрутка вверх и вниз также влияет на поля прокрутки. Прокрутка вверх и вниз не влияет на строки за пределами полей прокрутки.

Значение по умолчанию для <n> равно 1 (его можно опустить).

Изменение текста

Все команды в этом разделе обычно эквивалентны вызову API-интерфейсов консоли FillConsoleOutputCharacter, FillConsoleOutputAttribute и ScrollConsoleScreenBuffer для изменения содержимого буфера текста.

Sequence Код Описание Поведение
ESC [ <n> @ ICH Вставка символа Вставка <n> пробелов в текущую позицию курсора со сдвигом всего существующего текста вправо. Текст, который выходит за экран справа, удаляется.
ESC [ <n> P DCH Удаление символа Удаление <n> символов в текущей позиции курсора со сдвигом пробелов с правого края экрана.
ESC [ <n> X ECH Стереть символ Очистка <n> символов из текущей позиции курсора с заменой их символом пробела.
ESC [ <n> L IL Вставка строки Вставка <n> строк в буфер в позицию курсора. Строка, на которой находится курсор, и строки под ней будут сдвинуты вниз.
ESC [ <n> M DL Удалить строку Удаляет <n> строк из буфера, начиная со строки, в которой находится курсор.

Примечание.

Для IL и DL затрагиваются только строки в полях прокрутки (см. раздел "Поля прокрутки"). Если поля не заданы, то границами полей по умолчанию является текущее окно просмотра. Если линии будут сдвинуты ниже полей, они удалятся. При удалении строк в нижней части полей вставляются пустые строки, а строки за пределами окна просмотра никогда не затрагиваются.

Значение по умолчанию для <n> для каждой последовательности равно 0 (если оно опущено).

Для следующих команд параметр <n> имеет три допустимых значения:

  • 0 — очищает все данные с текущей позиции курсора (включительно) до конца строки или экрана;
  • 1 — очищает все данные с начала строки или экрана до текущей позиции курсора (включительно);
  • 2 — очищает всю строку или экран.
Sequence Код Описание Поведение
ESC [ <n> J ED Стереть на экране Заменяет весь текст в текущем окне просмотра или на экране, указанный параметром <n>, пробелами.
ESC [ <n> K EL Стереть в строке Заменить весь текст в строке с курсором, указанный параметром <n>, пробелами

Форматирование текста

Все команды в этом разделе обычно эквивалентны вызову API консоли SetConsoleTextAttribute для изменения форматирования всех будущих операций записи в буфер текста, выводимого на консоль.

Отличие этой команды заключается в том, что позиция <n>, указанная ниже, может принимать от 0 до 16 параметров, разделенных точкой с запятой.

Если параметры не указаны, все они обрабатываются как единственный параметр 0.

Sequence Код Описание Поведение
ESC [ <n> m SGR Установка графического отображения Установка формата экрана и текста, как указано <n>

Указанная ниже таблица значений может использоваться для <n>, чтобы отобразить различные режимы форматирования.

Режимы форматирования применяются слева направо. Если применить конкурирующие параметры форматирования, крайний правый параметр будет приоритетным.

Для параметров, задающих цвета, будут использованы цвета, указанные в таблице цветов консоли, которую можно изменить с помощью API SetConsoleScreenBufferInfoEx. Если таблица изменена так, что "синяя" позиция в таблице отображает оттенок красного цвета RGB, то все вызовы синего цвета переднего плана будут отображать этот красный цвет до тех пор, пока не будет указано иное.

значение Описание Поведение
0 По умолчанию Возвращает все атрибуты в состояние по умолчанию до изменения
1 Глубокий/яркий Применяет флаг яркости/интенсивности к цвету переднего плана
22 Неглубокий/неяркий Удаляет флаг яркости/интенсивности для цвета переднего плана
4 Подчеркнутый Добавляет подчеркивание
24 Нет подчеркивания Удаляет подчеркивание
7 Отрицательные Меняет местами цвет переднего плана и фона
27 Позитив (не негатив) Возвращает передний план и фон в обычное состояние
30 Черный цвет переднего плана Применяет неглубокий/яркий черный цвет для переднего плана
31 Красный цвет переднего плана Применяет неглубокий/яркий красный цвет для переднего плана
32 Зеленый цвет переднего плана Применяет неглубокий/яркий зеленый цвет для переднего плана
33 Желтый цвет переднего плана Применяет неглубокий/яркий желтый цвет для переднего плана
34 Синий цвет переднего плана Применяет неглубокий/яркий синий цвет для переднего плана
35 Пурпурный цвет переднего плана Применяет неглубокий/яркий пурпурный цвет для переднего плана
36 Голубой цвет переднего плана Применяет неглубокий/яркий голубой цвет для переднего плана
37 Белый цвет переднего плана Применяет неглубокий/яркий белый цвет для переднего плана
38 Дополнительные цвета для переднего плана Применяет дополнительные значения цвета для переднего плана (см. сведения ниже)
39 Цвет текста по умолчанию для переднего плана Применяет для переднего плана только цвета по умолчанию (см. 0)
40 Черный цвет фона Применяет неглубокий/яркий черный цвет для фона
41 Красный цвет фона Применяет неглубокий/яркий красный цвет для фона
42 Зеленый цвет фона Применяет неглубокий/яркий зеленый цвет для фона
43 Желтый цвет фона Применяет неглубокий/яркий желтый цвет для фона
44 Синий цвет фона Применяет неглубокий/яркий синий цвет для фона
45 Пурпурный цвет фона Применяет неглубокий/яркий пурпурный цвет для фона
46 Голубой цвет фона Применяет неглубокий/яркий голубой цвет для фона
47 Белый цвет фона Применяет неглубокий/яркий белый цвет для фона
48 Дополнительные цвета для фона Применяет дополнительные значения цвета для фона (см. сведения ниже)
49 Цвет текста по умолчанию для фона Применяет для фона только цвета по умолчанию (см. 0)
90 Ярко-черный цвет переднего плана Применяет глубокий/яркий черный цвет для переднего плана
91 Ярко-красный цвет переднего плана Применяет глубокий/яркий красный цвет для переднего плана
92 Ярко-зеленый цвет переднего плана Применяет глубокий/яркий зеленый цвет для переднего плана
93 Ярко-желтый цвет переднего плана Применяет глубокий/яркий желтый цвет для переднего плана
94 Ярко-синий цвет переднего плана Применяет глубокий/яркий синий цвет для переднего плана
95 Ярко-пурпурный цвет переднего плана Применяет глубокий/яркий пурпурный цвет для переднего плана
96 Ярко-голубой цвет переднего плана Применяет глубокий/яркий голубой цвет для переднего плана
97 Ярко-белый цвет переднего плана Применяет глубокий/яркий белый цвет для переднего плана
100 Ярко-черный цвет фона Применяет глубокий/яркий черный цвет для фона
101 Ярко-красный цвет фона Применяет глубокий/яркий красный цвет для фона
102 Ярко-зеленый цвет фона Применяет глубокий/яркий зеленый цвет для фона
103 Ярко-желтый цвет фона Применяет глубокий/яркий желтый цвет для фона
104 Ярко-синий цвет фона Применяет глубокий/яркий синий цвет для фона
105 Ярко-пурпурный цвет фона Применяет глубокий/яркий пурпурный цвет для фона
106 Ярко-голубой цвет фона Применяет глубокий/яркий голубой цвет для фона
107 Ярко-белый цвет фона Применяет глубокий/яркий белый цвет для фона

Дополнительные цвета

Некоторые эмуляторы виртуального терминала поддерживают палитру, превышающую 16 цветов, которые предоставляет консоль Windows. Для этих дополнительных цветов консоль Windows выберет ближайший подходящий цвет из существующей 16-цветной таблицы для отображения. В отличие от приведенных выше стандартных значений SGR, после первоначального обозначения дополнительные значения будут использовать дополнительные параметры в соответствии с таблицей ниже.

Подпоследовательность SGR Description
38 ; 2 ; <r> ; <g> ; <b> Задайте для цвета переднего плана значение RGB, указанное в <r>, <g>, <b> parameters*
48 ; 2 ; <r> ; <g> ; <b> Задайте для цвета фона значение RGB, указанное в <r>, g>, <<b> parameters*
38 ; 5 ; <s> Задайте цвет переднего плана индексу <> в таблице цветов 88 или 256*
48 ; 5 ; <s> Задайте цвет фона> индексу <в таблице цветов 88 или 256*

*Палитры цветов 88 и 256, поддерживаемые внутренне для сравнения, основаны на эмуляторе терминала xterm. В настоящее время невозможно изменить таблицы сравнения/округления.

Цвета экрана

Приведенная ниже команда позволяет приложению установить для значения палитры цветов экрана любое значение RGB.

Значения RGB должны быть в шестнадцатеричном формате в диапазоне от 0 до ff и разделяться символом косой черты (например, rgb:1/24/86).

Обратите внимание, что эта последовательность является последовательностью OSC "Команда операционной системы", а не CSI, как и многие другие последовательности, перечисленные, и как таковое, начинается с "\x1b], а не "\x1b[". Как последовательности OSC, они заканчиваются строковым терминатором, представленным как <ST> и передаваемые с ESC \ (0x1B 0x5C). Вместо признака конца строки можно использовать BEL (0x7), но рекомендуется использовать более длинную форму.

Последовательность Description Поведение
ESC ] 4; <i>; rgb: <r> / g> / <<b><ST> Изменение цветов экрана Задает индекс палитры цветов экрана <i> для значений RGB, указанных в <r>, <g>, <b>

Изменения режима

Существуют последовательности, управляющие режимами ввода. Существует два разных набора режимов ввода: режим клавиш курсора и режим клавиш дополнительной клавиатуры. Режим клавиш курсора управляет последовательностями, которые сформированы клавишами со стрелками, а также клавишами Home и End. Режим клавиш дополнительной клавиатуры управляет в основном последовательностями, созданными клавишами цифровой клавиатуры, а также функциональными клавишами.

Каждый из этих режимов представляет собой простые логические параметры: режим клавиш курсора — "Обычный" (по умолчанию) или "Приложение", а режим клавиш дополнительной клавиатуры — "Числовой" (по умолчанию) или "Приложение".

Последовательности, созданные в этих режимах, см. в разделах о клавишах курсора и о цифровых и функциональных клавишах.

Sequence Код Описание Поведение
ESC = DECKPAM Включение режима приложения для дополнительной клавиатуры Клавиши дополнительной клавиатуры будут создавать последовательности в режиме приложения.
ESC > DECKPNM Включение числового режима для дополнительной клавиатуры Клавиши дополнительной клавиатуры будут создавать последовательности в числовом режиме.
ESC [ ? 1 ч DECCKM Включение режима приложения для клавиш курсора Клавиши дополнительной клавиатуры будут создавать последовательности в режиме приложения.
ESC [ ? 1 l DECCKM Выключение режима приложения для клавиш курсора (использование обычного режима) Клавиши дополнительной клавиатуры будут создавать последовательности в числовом режиме.

Состояние запроса

Все команды в этом разделе обычно эквивалентны вызову API консоли Get* для получения сведений о состоянии текущего состояния буфера консоли.

Примечание.

Эти запросы будут выдавать свои ответы в поток входных данных консоли сразу после того, как он распознается в выходном потоке, а ENABLE_VIRTUAL_TERMINAL_PROCESSING задано. Флаг ENABLE_VIRTUAL_TERMINAL_INPUT не применяется к командам запросов, так как предполагается, что приложение, выполняющее запрос, всегда хочет получить ответ.

Sequence Код Описание Поведение
ESC [ 6 n DECXCPR Отчет о позиции курсора Выведите позицию курсора следующим образом: ESC [ <r> ; <c> R Where <r> = строка курсора и <c> = столбец курсора
ESC [ 0 c DA Атрибуты устройства Сообщает об идентификаторе терминала. Выдаст "\x1b[?1; 0c, указывающий "VT101 без параметров".

Символы табуляции

Хотя консоль Windows традиционно ожидает, что вкладки будут исключительно восемь символов широкими, *nix приложения, использующие определенные последовательности, могут управлять тем, где остановки вкладок находятся в окнах консоли для оптимизации перемещения курсора приложением.

Следующие последовательности позволяют приложению задавать расположения позиции табуляции в окне консоли, удалять их, а также перемещаться между ними.

Sequence Код Описание Поведение
ESC H HTS Установка горизонтальной табуляции Задает позицию табуляции в текущем столбце, в котором находится курсор.
ESC [ <n> I CHT Горизонтальная табуляция курсора (вперед) Перемещение курсора к следующему столбцу (в той же строке) в соответствии с позицией табуляции. Если больше нет позиций табуляции, выполняется перемещение к последнему столбцу в строке. Если курсор находится в последнем столбце, выполняется перемещение к первому столбцу следующей строки.
ESC [ <n> Z CBT Обратная табуляция курсора Перемещение курсора к предыдущему столбцу (в той же строке) в соответствии с позицией табуляции. Если больше нет позиций табуляции, выполняется перемещение курсора к первому столбцу. Если курсор находится в первом столбце, то он не перемещается.
ESC [ 0 г TBC Очистка позиции табуляции (текущий столбец) Очищает позицию табуляции в текущем столбце, если она есть. В противном случае ничего не происходит.
ESC [ 3 г TBC Очистка позиции табуляции (все столбцы) Очищает все установленные позиции табуляции.
  • Для CHT и CBT <n> является необязательным параметром (по умолчанию равно 1), указывающим, сколько раз следует передвинуть курсор в указанном направлении.
  • Если позиции табуляции не заданы через HTS, то CHT и CBT будут рассматривать первый и последний столбцы окна как единственные позиции табуляции.
  • При использовании HTS для установки остановки табуляции консоль также приведет к переходу к следующей остановке табуляции в выходных данных символа TAB (0x09, '\t') таким же образом, как CHT.

Назначение набора символов

Следующие последовательности позволяют программе изменять сопоставление активного набора символов. Это позволяет программе выдавать 7-битные символы кодировки ASCII, но отображать их как другие глифы на экране терминала. В настоящее время единственными поддерживаемыми наборами символов являются ASCII (по умолчанию) и специальный набор графических символов в кодировке DEC. Список всех символов, представленных в наборе графических символов в кодировке DEC, см. по этому адресу http://vt100.net/docs/vt220-rm/table2-4.html.

Последовательность Description Поведение
ESC ( 0 Назначение набора символов — рисование линии DEC Включает режим рисования линии DEC
ESC ( B Назначение набора символов — US ASCII Включает режим ASCII (по умолчанию)

Обратите внимание, что режим рисования линии DEC используется для очерчивания границ в консольных приложениях. В следующей таблице показано, какой символ ASCII соответствует символу рисования линии.

Hex ASCII Рисование линии DEC
0x6a j
0x6b тыс.
0x6c l
0x6d m
0x6e n
0x71 к
0x74 t
0x75 u
0x76 v
0x77 w
0x78 x

Поля прокрутки

Следующие последовательности позволяют программе настроить область прокрутки экрана, на которую влияют операции прокрутки. Это подмножество строк, которые настраиваются, когда экран будет прокручиваться в противном случае, например, на "\n" или RI. Эти поля также влияют на строки, измененные при выполнении операций вставки строки (IL), удаления строки (DL), прокрутки вверх (SU) и прокрутки вниз (SD).

Поля прокрутки могут особенно пригодиться для отображения части экрана, которая не прокручивается при заполнении остальной части экрана. Например, заголовок окна вверху или строка состояния в нижней части приложения.

Для DECSTBM есть два необязательных параметра: <t> и <b>. Они используются для указания строк, представляющих верхние и нижние строки области прокрутки (включительно). Если параметры не указаны, <t> по умолчанию равно 1, а <b> — текущей высоте окна просмотра.

Поля прокрутки задаются для каждого буфера, поэтому важно, чтобы альтернативный и основной буфер поддерживали отдельные параметры полей прокрутки (таким образом полноэкранное приложение в альтернативном буфере не навредит полям основного буфера).

Sequence Код Описание Поведение
ESC [ <t> ; <b> r DECSTBM Установка области прокрутки Задает поля прокрутки VT в окне просмотра.

Заголовок окна

Указанные ниже команды позволяют приложению задать для заголовка окна консоли значение указанного параметра <string>. Допустимое количество символов в строке не должно превышать 255. Это эквивалентно вызову SetConsoleTitle с заданной строкой.

Обратите внимание, что эти последовательности являются последовательностями OSC "Команда операционной системы", а не CSI, как и многие другие последовательности, перечисленные, и как это начинается с "\x1b], а не "\x1b[". Как последовательности OSC, они заканчиваются строковым терминатором, представленным как <ST> и передаваемые с ESC \ (0x1B 0x5C). Вместо признака конца строки можно использовать BEL (0x7), но рекомендуется использовать более длинную форму.

Последовательность Description Поведение
ESC ] 0; <Строка><ST> Установка заголовка окна Задает для заголовка окна консоли значение <string>.
ESC ] 2; <Строка><ST> Установка заголовка окна Задает для заголовка окна консоли значение <string>.

Завершающий символ здесь — символ "Колокол", "\x07"

Альтернативный буфер экрана

*Приложения стилей Nix часто используют альтернативный буфер экрана, чтобы они могли изменять все содержимое буфера, не влияя на запущенное приложение. Альтернативный буфер точно соответствует размеру окна без области обратной прокрутки.

В качестве примера такого поведения рассмотрим запуск Vim из Bash. Vim использует весь экран для редактирования файла, а затем возвращается к Bash, не затрагивая исходный буфер.

Последовательность Description Поведение
ESC [ ? 1 0 4 9 h Использование альтернативного буфера экрана Переключается на новый альтернативный буфер экрана.
ESC [ ? 1 0 4 9 l Использование основного буфера экрана Переключается на основной буфер.

Ширина окна

Для управления шириной окна консоли можно использовать следующие последовательности. Они примерно эквивалентны вызову API консоли SetConsoleScreenBufferInfoEx для установки ширины окна.

Sequence Код Описание Поведение
ESC [ ? 3 h DECCOLM Установка для числа столбцов значения 132 Задает ширину консоли в 132 столбца.
ESC [ ? 3 l DECCOLM Установка для числа столбцов значения 80 Задает ширину консоли в 80 столбцов.

Программный сброс

Для сброса некоторых свойств к значениям по умолчанию можно использовать указанную ниже последовательность. Следующие свойства сбрасываются к значениям по умолчанию (также перечислены последовательности, управляющие этими свойствами):

  • Видимость курсора: видимый (DECTEM).
  • Числовая клавиатура: числовой режим (DECNKM)
  • Режим ключей курсора: обычный режим (DECCKM)
  • Верхние и нижние поля: top=1, Bottom=Console height (DECS ТБ M)
  • Набор символов: US ASCII
  • Представление графики: по умолчанию или отключению (SGR)
  • Сохранение состояния курсора: положение дома (0,0) (DECSC)
Sequence Код Описание Поведение
ESC [ ! п DECSTR Программный сброс Сбрасывает некоторые параметры терминала к значениям по умолчанию.

Входные последовательности

Следующие последовательности терминалов создаются узлом консоли во входном потоке, если флаг ENABLE_VIRTUAL_TERMINAL_INPUT установлен в дескриптор входного буфера с помощью флага SetConsoleMode.

Существует два внутренних режима, определяющих, какие последовательности выдаются для заданных клавиш ввода: режим клавиш курсора и режим клавиш дополнительной клавиатуры. Они подробно описаны в разделе "Изменения режима".

Клавиши курсора

Ключ. Обычный режим Режим приложения
Стрелка вверх ESC [ A ESC O A
Стрелка вниз ESC [ B ESC O B
Стрелка вправо ESC [ C ESC O C
Стрелка влево ESC [ D ESC O D
HOME ESC [ H ESC O H
Завершить ESC [ F ESC O F

Кроме того, если нажать клавишу Ctrl с любой из этих клавиш, будут выданы указанные ниже последовательности, независимо от режима клавиш курсора:

Ключ. Любой режим
CTRL+СТРЕЛКА ВВЕРХ ESC [ 1; 5 A
CTRL+СТРЕЛКА ВНИЗ ESC [ 1; 5 B
CTRL+СТРЕЛКА ВПРАВО ESC [ 1; 5 C
CTRL +СТРЕЛКА ВЛЕВО ESC [ 1; 5 D

Клавиши цифровой клавиатуры и функциональные клавиши

Ключ. Sequence
Backspace 0x7f (DEL)
Пауза 0x1a (SUB)
ESCAPE 0x1b (ESC)
Insert ESC [ 2 ~
DELETE ESC [ 3 ~
Page Up ESC [ 5 ~
Page Down ESC [ 6 ~
F1 ESC O P
F2 ESC O Q
F3 ESC O R
F4 ESC O S
F5 ESC [ 1 5 ~
F6 ESC [ 1 7 ~
F7 ESC [ 1 8 ~
F8 ESC [ 1 9 ~
F9 ESC [ 2 0 ~
F10 ESC [ 2 1 ~
F11 ESC [ 2 3 ~
F12 ESC [ 2 4 ~

Модификаторы

Alt обрабатывается префиксом последовательности с помощью escape-файла: ESC <c> , где <c> — символ, передаваемый операционной системой. Alt+Ctrl обрабатывается аналогичным образом, за исключением того, что у операционной системы будет предварительно сдвинута клавиша <c> на соответствующий управляющий символ, который будет передаваться в приложение.

Обычно передача Ctrl выполняется точно так же, как и при получении от системы. Обычно это один символ, который сдвинут вниз в зарезервированное пространство управляющего символа (0x0-0x1f). Например, ctrl+@ (0x40) становится NUL (0x00), CTRL+[ (0x5b) становится ESC (0x1b) и т. д. Несколько сочетаний клавиш CTRL обрабатываются специально в следующей таблице:

Ключ. Sequence
CTRL+ПРОБЕЛ 0x00 (NUL)
CTRL+СТРЕЛКА ВВЕРХ ESC [ 1; 5 A
CTRL+СТРЕЛКА ВНИЗ ESC [ 1; 5 B
CTRL+СТРЕЛКА ВПРАВО ESC [ 1; 5 C
CTRL +СТРЕЛКА ВЛЕВО ESC [ 1; 5 D

Примечание.

Левый Ctrl+ правый Alt обрабатывается как AltGr. При одновременном отображении они будут удалены, а значение символа Юникода, представленного системой, будет передано в целевой объект. Система будет предварительно преобразовывать значения AltGr в соответствии с текущими входными параметрами системы.

Примеры

Пример последовательностей терминала SGR

Следующий код содержит несколько примеров форматирования текста.

#include <stdio.h>
#include <wchar.h>
#include <windows.h>

int main()
{
    // Set output mode to handle virtual terminal sequences
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hOut == INVALID_HANDLE_VALUE)
    {
        return GetLastError();
    }

    DWORD dwMode = 0;
    if (!GetConsoleMode(hOut, &dwMode))
    {
        return GetLastError();
    }

    dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
    if (!SetConsoleMode(hOut, dwMode))
    {
        return GetLastError();
    }

    // Try some Set Graphics Rendition (SGR) terminal escape sequences
    wprintf(L"\x1b[31mThis text has a red foreground using SGR.31.\r\n");
    wprintf(L"\x1b[1mThis text has a bright (bold) red foreground using SGR.1 to affect the previous color setting.\r\n");
    wprintf(L"\x1b[mThis text has returned to default colors using SGR.0 implicitly.\r\n");
    wprintf(L"\x1b[34;46mThis text shows the foreground and background change at the same time.\r\n");
    wprintf(L"\x1b[0mThis text has returned to default colors using SGR.0 explicitly.\r\n");
    wprintf(L"\x1b[31;32;33;34;35;36;101;102;103;104;105;106;107mThis text attempts to apply many colors in the same command. Note the colors are applied from left to right so only the right-most option of foreground cyan (SGR.36) and background bright white (SGR.107) is effective.\r\n");
    wprintf(L"\x1b[39mThis text has restored the foreground color only.\r\n");
    wprintf(L"\x1b[49mThis text has restored the background color only.\r\n");

    return 0;
}

Примечание.

В предыдущем примере строка '\x1b[31m' является реализацией ESC [ <n> m с <n> 31.

На следующем рисунке показаны выходные данные предыдущего примера кода.

output of the console using the sgr command

Пример включения обработки виртуального терминала

В следующем коде приведен пример рекомендуемого способа включения обработки виртуального терминала для приложения. Цель примера — продемонстрировать, что:

  1. Существующий режим всегда должен извлекаться через GetConsoleMode и анализироваться, прежде чем он будет задан с помощью SetConsoleMode.

  2. Проверка того, возвращается 0 ли SetConsoleMode и GetLastError возвращает ERROR_INVALID_PARAMETER является текущим механизмом для определения при запуске в системе нижнего уровня. Приложение, получающее ERROR_INVALID_PARAMETER с одним из более новых флагов режима консоли в битовом поле, должно корректно снизить поведение и повторить попытку.

#include <stdio.h>
#include <wchar.h>
#include <windows.h>

int main()
{
    // Set output mode to handle virtual terminal sequences
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hOut == INVALID_HANDLE_VALUE)
    {
        return false;
    }
    HANDLE hIn = GetStdHandle(STD_INPUT_HANDLE);
    if (hIn == INVALID_HANDLE_VALUE)
    {
        return false;
    }

    DWORD dwOriginalOutMode = 0;
    DWORD dwOriginalInMode = 0;
    if (!GetConsoleMode(hOut, &dwOriginalOutMode))
    {
        return false;
    }
    if (!GetConsoleMode(hIn, &dwOriginalInMode))
    {
        return false;
    }

    DWORD dwRequestedOutModes = ENABLE_VIRTUAL_TERMINAL_PROCESSING | DISABLE_NEWLINE_AUTO_RETURN;
    DWORD dwRequestedInModes = ENABLE_VIRTUAL_TERMINAL_INPUT;

    DWORD dwOutMode = dwOriginalOutMode | dwRequestedOutModes;
    if (!SetConsoleMode(hOut, dwOutMode))
    {
        // we failed to set both modes, try to step down mode gracefully.
        dwRequestedOutModes = ENABLE_VIRTUAL_TERMINAL_PROCESSING;
        dwOutMode = dwOriginalOutMode | dwRequestedOutModes;
        if (!SetConsoleMode(hOut, dwOutMode))
        {
            // Failed to set any VT mode, can't do anything here.
            return -1;
        }
    }

    DWORD dwInMode = dwOriginalInMode | dwRequestedInModes;
    if (!SetConsoleMode(hIn, dwInMode))
    {
        // Failed to set VT input mode, can't do anything here.
        return -1;
    }

    return 0;
}

Пример выбора функций юбилейного обновления

Следующий пример представляет собой более надежный пример кода, использующий разнообразные escape-последовательности для работы с буфером, с акцентом на возможности, добавленные в юбилейном обновлении для Windows 10.

В этом примере используется альтернативный буфер экрана, выполняется управление позициями табуляции, установка полей прокрутки и изменение набора символов.

// System headers
#include <windows.h>

// Standard library C-style
#include <wchar.h>
#include <stdlib.h>
#include <stdio.h>

#define ESC "\x1b"
#define CSI "\x1b["

bool EnableVTMode()
{
    // Set output mode to handle virtual terminal sequences
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hOut == INVALID_HANDLE_VALUE)
    {
        return false;
    }

    DWORD dwMode = 0;
    if (!GetConsoleMode(hOut, &dwMode))
    {
        return false;
    }

    dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
    if (!SetConsoleMode(hOut, dwMode))
    {
        return false;
    }
    return true;
}

void PrintVerticalBorder()
{
    printf(ESC "(0"); // Enter Line drawing mode
    printf(CSI "104;93m"); // bright yellow on bright blue
    printf("x"); // in line drawing mode, \x78 -> \u2502 "Vertical Bar"
    printf(CSI "0m"); // restore color
    printf(ESC "(B"); // exit line drawing mode
}

void PrintHorizontalBorder(COORD const Size, bool fIsTop)
{
    printf(ESC "(0"); // Enter Line drawing mode
    printf(CSI "104;93m"); // Make the border bright yellow on bright blue
    printf(fIsTop ? "l" : "m"); // print left corner 

    for (int i = 1; i < Size.X - 1; i++)
        printf("q"); // in line drawing mode, \x71 -> \u2500 "HORIZONTAL SCAN LINE-5"

    printf(fIsTop ? "k" : "j"); // print right corner
    printf(CSI "0m");
    printf(ESC "(B"); // exit line drawing mode
}

void PrintStatusLine(const char* const pszMessage, COORD const Size)
{
    printf(CSI "%d;1H", Size.Y);
    printf(CSI "K"); // clear the line
    printf(pszMessage);
}

int __cdecl wmain(int argc, WCHAR* argv[])
{
    argc; // unused
    argv; // unused
    //First, enable VT mode
    bool fSuccess = EnableVTMode();
    if (!fSuccess)
    {
        printf("Unable to enter VT processing mode. Quitting.\n");
        return -1;
    }
    HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
    if (hOut == INVALID_HANDLE_VALUE)
    {
        printf("Couldn't get the console handle. Quitting.\n");
        return -1;
    }

    CONSOLE_SCREEN_BUFFER_INFO ScreenBufferInfo;
    GetConsoleScreenBufferInfo(hOut, &ScreenBufferInfo);
    COORD Size;
    Size.X = ScreenBufferInfo.srWindow.Right - ScreenBufferInfo.srWindow.Left + 1;
    Size.Y = ScreenBufferInfo.srWindow.Bottom - ScreenBufferInfo.srWindow.Top + 1;

    // Enter the alternate buffer
    printf(CSI "?1049h");

    // Clear screen, tab stops, set, stop at columns 16, 32
    printf(CSI "1;1H");
    printf(CSI "2J"); // Clear screen

    int iNumTabStops = 4; // (0, 20, 40, width)
    printf(CSI "3g"); // clear all tab stops
    printf(CSI "1;20H"); // Move to column 20
    printf(ESC "H"); // set a tab stop

    printf(CSI "1;40H"); // Move to column 40
    printf(ESC "H"); // set a tab stop

    // Set scrolling margins to 3, h-2
    printf(CSI "3;%dr", Size.Y - 2);
    int iNumLines = Size.Y - 4;

    printf(CSI "1;1H");
    printf(CSI "102;30m");
    printf("Windows 10 Anniversary Update - VT Example");
    printf(CSI "0m");

    // Print a top border - Yellow
    printf(CSI "2;1H");
    PrintHorizontalBorder(Size, true);

    // // Print a bottom border
    printf(CSI "%d;1H", Size.Y - 1);
    PrintHorizontalBorder(Size, false);

    wchar_t wch;

    // draw columns
    printf(CSI "3;1H");
    int line = 0;
    for (line = 0; line < iNumLines * iNumTabStops; line++)
    {
        PrintVerticalBorder();
        if (line + 1 != iNumLines * iNumTabStops) // don't advance to next line if this is the last line
            printf("\t"); // advance to next tab stop

    }

    PrintStatusLine("Press any key to see text printed between tab stops.", Size);
    wch = _getwch();

    // Fill columns with output
    printf(CSI "3;1H");
    for (line = 0; line < iNumLines; line++)
    {
        int tab = 0;
        for (tab = 0; tab < iNumTabStops - 1; tab++)
        {
            PrintVerticalBorder();
            printf("line=%d", line);
            printf("\t"); // advance to next tab stop
        }
        PrintVerticalBorder();// print border at right side
        if (line + 1 != iNumLines)
            printf("\t"); // advance to next tab stop, (on the next line)
    }

    PrintStatusLine("Press any key to demonstrate scroll margins", Size);
    wch = _getwch();

    printf(CSI "3;1H");
    for (line = 0; line < iNumLines * 2; line++)
    {
        printf(CSI "K"); // clear the line
        int tab = 0;
        for (tab = 0; tab < iNumTabStops - 1; tab++)
        {
            PrintVerticalBorder();
            printf("line=%d", line);
            printf("\t"); // advance to next tab stop
        }
        PrintVerticalBorder(); // print border at right side
        if (line + 1 != iNumLines * 2)
        {
            printf("\n"); //Advance to next line. If we're at the bottom of the margins, the text will scroll.
            printf("\r"); //return to first col in buffer
        }
    }

    PrintStatusLine("Press any key to exit", Size);
    wch = _getwch();

    // Exit the alternate buffer
    printf(CSI "?1049l");

}