Skip to content

Instantly share code, notes, and snippets.

@dvmn-tasks
Last active October 6, 2022 19:02
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save dvmn-tasks/d5ec61b37ac62adcf29665381c545131 to your computer and use it in GitHub Desktop.
Save dvmn-tasks/d5ec61b37ac62adcf29665381c545131 to your computer and use it in GitHub Desktop.

Введение

Есть много программ, печатающих что-нибудь в терминал. Но их можно сильно разнообразить: можно покрасить текст, двигать курсор или переписать какой-нибудь текст поверх старого. Благодаря этому в Git красивые прогресс-бары, а Vim и Nano позволяют редактировать текст внутри терминала, как будто это происходит в обычном блокноте.

Существуют библиотеки, которые помогают в такой работе с терминалом. Но куда круче научиться делать это самостоятельно. В этой статье мы рассмотрим, что можно сделать простой командой print в Python.

Большинство программ взаимодействуют с терминалом через управляющие коды ANSI. Это специальные инструкции для терминала. В терминалах разных систем поддерживаются разные коды. В Википедии есть список поддерживаемых кодов. В этой статье мы научимся работать с терминалами Unix систем: Ubuntu или OS-X. Но не на Windows, это отдельное приключение.

Оглавление

Покраска текста

Начнём с простого вывода в консоль:

sample text

Так выглядит обычный, не покрашенный текст.

Красный

Самое простое, что можно сделать с текстом, это покрасить его. ANSI коды для этого выглядят так:

  • Красный: \u001b[31m
  • Вернуть как было: \u001b[0m

С комбинации \u001b начинаются большинство ANSI кодов. Вот как покрасить Hello, World!:

sample text

Если присмотреться, можно заметить, что покрасилась не только фраза Hello, World!, но и всё что под ней. Терминал получил команду "Теперь выводи всё красным", поэтому он покрасил всё, что мы вводили далее. Как вы видите, он прекратил "красный" вывод, когда получил команду "Верни как было": \u001b[0m.

Чтобы получилось аккуратно, лучше ставить команду "Верни как было" сразу после фразы:

sample text

Больше цветов

С этим разобрались, а как ещё можно красить? У большинства терминалов есть 8 базовых цветов:

Цвет Код
Чёрный \u001b[30m
Красный \u001b[31m
Зелёный \u001b[32m
Жёлтый \u001b[33m
Синий \u001b[34m
Пурпурный \u001b[35m
Голубой \u001b[36m
Белый \u001b[37m
Сброс цвета \u001b[0m

sample text

Чтобы сделать цвет ярче, можно прибавить к коду ;1. Получается ещё 8 цветов:

Цвет Код
Яркий чёрный \u001b[30;1m
Яркий красный \u001b[31;1m
Яркий зелёный \u001b[32;1m
Яркий жёлтый \u001b[33;1m
Яркий синий \u001b[34;1m
Яркий пурпурный \u001b[35;1m
Яркий голубой \u001b[36;1m
Яркий белый \u001b[37;1m
Сброс цвета \u001b[0m

sample text

Все цвета

Всего в ANSI 256 цветов. Они составляются так: \u001b[38;5;КОДm, где вместо КОД — число от 0 до 255:

sample text

Покраска фона

Работает так же, только коды другие:

Цвет Код
Чёрный \u001b[40m
Красный \u001b[41m
Зелёный \u001b[42m
Жёлтый \u001b[43m
Синий \u001b[44m
Пурпурный \u001b[45m
Голубой \u001b[46m
Белый \u001b[47m

Сброс цвета такой же: \u001b[0m.

Либо можно собрать один из 256 доступных по схеме \u001b[48;5;КОДm, где вместо КОД — число от 0 до 255:

sample text

Навигация курсора

Некоторые виды ANSI-кодов могут двигать курсор внутри терминала:

Направление Код
Вверх \u001b[ШАГA
Вниз \u001b[ШАГB
Вправо \u001b[ШАГC
Влево \u001b[ШАГD

Вместо ШАГ нужно подставить нужное число, например, \u001b[10A — переведёт курсор на 10 строк вверх. Вот так это выглядит:

sample text

Мы вывели код, который поднимает курсор терминала на 10 строчек вверх, а потом напечатался текст. Как и ожидалось, он оказался выше, чем сама команда, которую мы вводили.

Очистка экрана

Перемещение курсора по экрану позволяет выводить один текст поверх другого, но это не всегда просто сделать:

print('Первая надпись на экране')
print('Это вторая надпись на экране')
print('\u001b[2A')
print('Третья надпись')

В результате получим абракадабру. Одна надпись наложилась поверх другой, но не затерла её полностью:

Первая надпись на экране
Третья надписьпись на экране

Эту проблему можно решить добавлением пробелов к коротким строкам, чтобы все получились одной ширины:

print('Первая надпись на экране')
print('Это вторая надпись на экране')
print('\u001b[2A')
print('Третья надпись              ')

Это работает, но очень неудобно: сложно менять текст сообщений и легко ошибиться с количеством пробелов. Если вы можете себе позволить очистить экран полностью, то воспользуйтесь спец.символом для очистки экрана '\033[2J':

print('Это первая надпись на экране')
print('\033[2J')  # очистит экран
print('Вторая надпись')

Теперь всё будет работать как надо:

Вторая надпись
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment