Контекст и вопрос
Есть много способов раскрасить среду терминала и оболочки. Вывод отдельных команд, таких как ls
и grep
, также может быть раскрашен. Непосредственно связанным, но тем не менее интересным является понятие воспроизведения мультимедиа на консоли, но, похоже, оно опирается на некоторые фреймворки (библиотеки) поверх оконной системы. Следующий вопрос направлен исключительно на bash
оболочку и ее реализацию в терминальной платформе Linux и ее основах.
Пожалуйста, рассмотрите следующий монтаж ASCII "визуализации" сцены в 2D игре :
Это не случайно сгенерированные сцены. Все сегменты, которые я выбрал, на самом деле изображают некоторую форму "лугопастбищного ландшафта" (деревья, кустарники и кустарники, цветы, трава и т. Д.) Из игры, в которой для представления таких объектов используются символы ASCII. Последние 4 сцены демонстрируют пользовательские наборы плиток, которые в основном представляют собой переназначение символов ASCII с цветовыми характеристиками (такие детали тривиальны - достаточно сказать, что это визуальное вдохновение для того, что я пытаюсь выполнить здесь с точки зрения визуальных эффектов и " шаблон").
Общие черты этих сцен в общей папке:
- Максимум 5-6 различных символов ASCII (запятые, кавычки и некоторые другие)
- Используется 2-4 цвета
- для персонажей
- для фонов персонажей в некоторых случаях - последний пример, чтобы показать использование цветовых оттенков с небольшим или без символа для создания узора, то есть цветная мозаика
На данный момент у меня есть виртуальная машина Arch Linux, и, хотя вопрос не относится к конкретному дистрибутиву, я изучил их документацию для настройки /etc/bash.bashrc
файла. Я вижу, что много объяснений идет в настройке внешнего вида приглашения и вообще всех элементов переднего плана. Существует мало информации о любой конфигурации для фона, за исключением обычно сплошного цвета, такого как эти настройки и советы :
# Background
On_Black='\e[40m' # Black
On_Red='\e[41m' # Red
On_Green='\e[42m' # Green
On_Yellow='\e[43m' # Yellow
On_Blue='\e[44m' # Blue
On_Purple='\e[45m' # Purple
On_Cyan='\e[46m' # Cyan
On_White='\e[47m' # White
Я до сих пор концептуально не понимаю, что это за пустые / пустые / фоновые "пробелы", которые я не печатал, когда использую консоль, т.е. "из чего они сделаны?" так сказать. Особенно те, которые не в приглашении, и которые оборачиваются вокруг команд, которые отображаются. Что касается того, что происходит на активной строке, то можно продемонстрировать, что она bash
действует «линейно-ориентированным» образом и что некоторые операции запускают очистку активной строки ( for i in $(seq 1 $(expr $(tput lines) \* $(tput cols))); do echo -n M; done; tput cup 15 1
затем в приглашении введите символ и нажмите клавишу Backspace - продемонстрировано участник) - степень, которая может варьироваться от CLI к другому, т.е. zsh. Кроме того, кажется, что когда я добавляю что-то вроде \[\033[44m\]
моей строки PS1, bash.bashrc
после перезагрузки bash я получаю синий фон - так что, очевидно, я знаю, что есть некоторыеиспользовать здесь выходной внешний вид, насколько это касается фона .
Но я также знаю, что bash - это часть программного обеспечения, полагающаяся на какое-то другое средство в виде подсистемы TTY для вывода объектов на экран - и это, как я полагаю, сводится к компоненту VT в ядре. pstree -Ap
на Arch показывает, systemd
связанные, login
а затем к bash
.
Arch Linux распределение зависит от agetty
услуг TTY. Простое echo $TERM
выдаст тип используемого терминала («linux» здесь вне любого DE), а infocmp[-d spec1 spec2]
команда без параметра показывает возможности активного терминала и информацию о профиле из базы данных терминала terminfo (5) :
# Reconstructed via infocmp from file: /usr/share/terminfo/l/linux
linux|linux console,
am, bce, ccc, eo, mir, msgr, xenl, xon,
colors#8, it#8, ncv#18, pairs#64,
acsc=+\020\,\021-\030.^Y0\333'\004a\261f\370g\361h\260i\316j\331k\277l\332m\300n\305o~p\304q\304r\304s_t\303u\264v\301w\302x\263y\363z\362{\343|\330}\234~\376,
bel=^G, blink=\E[5m, bold=\E[1m, civis=\E[?25l\E[?1c,
clear=\E[H\E[J, cnorm=\E[?25h\E[?0c, cr=^M,
csr=\E[%i%p1%d;%p2%dr, cub=\E[%p1%dD, cub1=^H,
cud=\E[%p1%dB, cud1=^J, cuf=\E[%p1%dC, cuf1=\E[C,
cup=\E[%i%p1%d;%p2%dH, cuu=\E[%p1%dA, cuu1=\E[A,
cvvis=\E[?25h\E[?8c, dch=\E[%p1%dP, dch1=\E[P, dim=\E[2m,
dl=\E[%p1%dM, dl1=\E[M, ech=\E[%p1%dX, ed=\E[J, el=\E[K,
el1=\E[1K, flash=\E[?5h\E[?5l$, home=\E[H,
hpa=\E[%i%p1%dG, ht=^I, hts=\EH, ich=\E[%p1%d@, ich1=\E[@,
il=\E[%p1%dL, il1=\E[L, ind=^J,
initc=\E]P%p1%x%p2%{255}%*%{1000}%/%02x%p3%{255}%*%{1000}%/%02x%p4%{255}%*%{1000}%/%02x,
kb2=\E[G, kbs=\177, kcbt=\E[Z, kcub1=\E[D, kcud1=\E[B,
kcuf1=\E[C, kcuu1=\E[A, kdch1=\E[3~, kend=\E[4~, kf1=\E[[A,
kf10=\E[21~, kf11=\E[23~, kf12=\E[24~, kf13=\E[25~,
kf14=\E[26~, kf15=\E[28~, kf16=\E[29~, kf17=\E[31~,
kf18=\E[32~, kf19=\E[33~, kf2=\E[[B, kf20=\E[34~,
kf3=\E[[C, kf4=\E[[D, kf5=\E[[E, kf6=\E[17~, kf7=\E[18~,
kf8=\E[19~, kf9=\E[20~, khome=\E[1~, kich1=\E[2~,
kmous=\E[M, knp=\E[6~, kpp=\E[5~, kspd=^Z, nel=^M^J, oc=\E]R,
op=\E[39;49m, rc=\E8, rev=\E[7m, ri=\EM, rmacs=\E[10m,
rmam=\E[?7l, rmir=\E[4l, rmpch=\E[10m, rmso=\E[27m,
rmul=\E[24m, rs1=\Ec\E]R, sc=\E7, setab=\E[4%p1%dm,
setaf=\E[3%p1%dm,
sgr=\E[0;10%?%p1%t;7%;%?%p2%t;4%;%?%p3%t;7%;%?%p4%t;5%;%?%p5%t;2%;%?%p6%t;1%;%?%p7%t;8%;%?%p9%t;11%;m,
sgr0=\E[0;10m, smacs=\E[11m, smam=\E[?7h, smir=\E[4h,
smpch=\E[11m, smso=\E[7m, smul=\E[4m, tbc=\E[3g,
u6=\E[%i%d;%dR, u7=\E[6n, u8=\E[?6c, u9=\E[c,
vpa=\E[%i%p1%dd,
В его нынешнем виде многие возможности могут быть использованы из инфраструктуры терминала, и в основном это те функции, которые представлены в файле конфигурации bash.bashrc, поскольку приглашение настраивается путем установки переменной PS1. Управляющие и управляющие последовательности используются для прерывания потока отображения символов в терминале для обеспечения функций, включая перемещение курсора и другие возможности, описанные в информационной базе данных терминала. Многие из этих функций передаются с использованием хорошо известного ESC[
(или \ 33) средства ввода управляющих последовательностей (больше последовательностей здесь и здесь , а также несколько примеров ). Кроме того, также можно использоватьtput
утилита непосредственно в CLI для изменения некоторых свойств терминала; например tput setab 4
, на синем фоне будут команды bash echo.
Если мы strace bash
увидим как escape-последовательности, так и поведение в действии:
write(2, "[il@Arch64vm1 ~]$ ", 19[il@Arch64vm1 ~]$ ) = 19 //bash starts
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
read(0, " ", 1) = 1 //pressed <space>
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, " ", 1 ) = 1
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
read(0, "\177", 1) = 1 //pressed <backspace>...
rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
write(2, "\10\33[K", ) = 4 //triggers erasing the line
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, NULL, [], 8) = 0
read(0, "\33", 1) = 1 //pressed <esc> per se
Это обеспечивает контекст для вопроса Можно ли заменить пустые пробелы / цвет фона в терминале случайным (но симпатичным) набором символов ASCII? но не дает представления о том, как реализовать функции или что я ищу в терминале.
Поэтому я создал грубый макет в качестве примера того, как конечный результат может выглядеть, если это возможно (не серьезно :):
По сути, все «пустое пространство» в терминале будет заполнено шаблоном (здесь я «рисую» одно изображение сверху, но мне бы хотелось, чтобы в реальной реализации каждая отдельная «пустая» генерировалась случайным образом из набора 5-6 символов и особенности, документированные из монтажа, которые будут указаны). Существует другая схема для активной командной строки, то есть волнистая «вода», но я бы остановился на синей линии. Как и предполагалось, команды будут «стирать» «воду», когда они набираются на активной строке, и, конечно, существует ограничение, заключающееся в том, что шаблон символов никогда не интерпретируется CLI, иначе это сделает его бесполезным.
Таким образом, есть ли какая-либо конфигурация, представленная в bash
или в самой структуре терминала, или сценарий, который позволил бы использовать набор символов и некоторый контроль над цветами, чтобы изменить вывод bash в терминале, чтобы сгенерировать несколько случайный образец для фона (что будет похоже на то, что я показал выше)? Или я должен просто согласиться на что-то вроде попытки предоставить полное изображение шаблона в качестве фона для tty ?
Реализации
0.1 - версия PatternOTD (одноразовая сделка при входе в систему)
Следующее выражение, которое я добавил в мой файл .bashrc, объединяет некоторые из рассмотренных нами понятий и представляет собой (очень) базовое доказательство концепции визуалов в стандартном терминале Linux:
for i in $(seq 1 $(expr $(tput lines))); do echo -en '\E[32;32m'$(tr -dc '",.;:~' < /dev/urandom | head -c $(tput cols)); done; tput cup 15; tput setab 4; echo -en "\E[2K"; tput setab 0
наблюдения
- Очевидно, что это просто команда, поэтому она не постоянна, т.е. она прокручивается по мере ввода команд
- Принято решение не индивидуально рандомизировать выбор символов, т. Е.
head -c 1
Сtput cols
умножением строк для начала, что будет печатать отдельные случайные символы из указанного в кавычках выбора - потому что это слишком медленно. Я не думаю, чтоrandom
генерирует длинное целое число (tput cols), но все же это быстрее. Конечно, это все очень расточительно, но это работает. - Не рандомизировал ни один цвет или эффект для символа или иным образом, за исключением этого зеленого, потому что, как я объяснил, рендеринг / обработка каждого символа в отдельности слишком медленная. Re: кадровый буфер?
- Я рад видеть, что шаблон не мешает использованию CLI в том смысле, что он не интерпретируется CLI! (почему, хотя я не мог объяснить)
- Вода ушла слишком быстро! ;-)
0.2 - PROMPT_COMMAND взломать работу
Значение переменной PROMPT_COMMAND проверяется непосредственно перед тем, как Bash напечатает каждое первичное приглашение. Я знаю, что обычно вы используете переменную для вызова скрипта, где вы можете обрабатывать элементы с экрана и т. Д., Но я скорее пытаюсь сделать это прямо в моем файле .bashrc. Первоначально я думал, что смогу реализовать некоторую позиционную осведомленность, т.е. где находится курсор перед выполнением (поэтому я мог рендерить вещи на экране в любом месте, а tput
затем возвращаться в прежнюю позицию, используя что-то вроде этого для извлечения позиции:
stty -echo; echo -n $'\e[6n'; read -d R x; stty echo; echo ${x#??} //value is in x;x format so...
Я хотел бы передать значение cut -f1 -d";"
. Я могу сделать это на CLI, но выполнение этой работы внутри последовательности элементов в переменных PS1 / P_C в данный момент мне недоступно, и возможно, что любая команда, введенная в PROMPT_COMMAND, может оцениваться не при каждом возврате каретки, а скорее только один раз (?), несмотря на то, что выполняется каждый раз (см. наблюдения ниже).
Поэтому лучшее, что я мог сделать, это перенести мою начальную последовательность и добавить некоторые команды как в PROMPT_COMMAND, так и в определение переменной PS1 в .bashrc. Вот так:
PROMPT_COMMAND="echo -en '\E[32;32m'$(tr -dc ',.:~' < /dev/urandom | head -c $(echo "$[$(tput cols) * 2]"))"
PS1="$(echo -en '\n') $(tput setab 4)$(echo -en "\E[2K")$(tput setab 0)\[\033[7;32m\]df:\[\033[1;34m\] \W @d \[\033[0m\]\e[32m"
for i in $(seq 1 $(expr $(tput lines))); do echo -en '\E[32;32m'$(tr -dc '",.;:~' < /dev/urandom | head -c $(tput cols)); done; tput cup 1; tput setab 4; echo -en "\E[2K"; tput setab 0
В итоге я использую P_C, чтобы попытаться реализовать постоянный визуальный шаблон, т.е. добавляются 2 строки. К сожалению, я не могу создать оба этих шаблона, повторяя мой «водяной» трюк, то есть активную линию синего цвета (которая просто меняет цвет фона, делает четкую линию, а затем меняет фон на черный). Я собрал изображение, чтобы показать, как это играет вместе:
наблюдения
- Использование backspace на линии по-прежнему вызывает поведение чистой линии, и синий исчез
- Каждый раз, когда нажимается клавиша ввода, у нас есть 2 строки шаблона перед новой активной строкой
- Конечно, как мы видим дальше, несмотря на дополнительные строки, мы не переносим шаблон на стороне команд, таких как
ls
- Случайность / dev / urandom кажется не такой случайной, когда вызывается здесь в P_C. Это изображение состоит из 2 изображений, но легко заметить, что шаблон из 2 дополнительных линий всегда одинаков, т.е. случайность генерируется не при каждом нажатии клавиши ввода, а только один раз для каждой из двух строк - возможно, только первой время .bashrc читается
bash
. - Содержимое переменной PS1 начинается с
$(echo -en '\n') $(tput setab 4)
- хорошо, что пространство там посередине, перед $ (tput ...), ДОЛЖНО быть там, чтобы это работало. В противном случае синяя линия появляется сверху подсказки, а не перед ней, и я не могу решить это. И это взлом, что дает свое название 0,2. :)
0,3 - tput cuu
&tput cud
for i in $(seq 1 $(expr $(tput lines))); do echo -en '\E[0;32m'$(tr -dc '",.o;:~' < /dev/urandom | head -c $(tput cols)); done; tput cup 1
PROMPT_COMMAND="echo -en '\033[0;32m$(tr -dc ',;o.:~' < /dev/urandom | head -c $(tput cols))\n\033[36;44m$(tr -dc '~' < /dev/urandom | head -c $(tput cols))\033[0;32m$(tr -dc ',.o+;:~' < /dev/urandom | head -c $(tput cols))'$(tput cuu 2)"
PS1="\[\033[0m\] \[\033[1;32m\][1]\[\033[7;32m\]=2=:\W)\[\033[0;32m\]=3=\[\033[1;32m\]=4=@>\[\033[0;32m\]"
Что сделано с PROMPT_COMMAND, так это то, что 3 линии шаблонов печатаются каждый раз перед генерацией приглашения - и эти 3 набора шаблонов генерируются индивидуально в пределах ограничений, объясненных в 0.2 - бессмысленно для воды, поскольку это 1 символ, но все же. Затем мы поднимаемся на две строки (используя tput cuu 2
), и подсказка генерируется в средней строке в соответствии с PS1. У нас все еще есть наш начальный набор команд для полноэкранного шаблона при загрузке .bashrc, который выполняется только один раз, когда мы подключаемся к терминалу. Теперь у нас есть несколько отступов вокруг активной строки, которая имеет свой собственный синий шаблон, который всегда повторяется при возврате каретки. Содержимое переменной PS1 и P_C очищено. Синтаксис escape-последовательностей и цветового кодирования, встроенных в longecho
последовательности могут быть хитрыми. Ошибки приводят к странному поведению терминалавключая строки, которые перезаписывают друг друга, подсказку, которая появляется за пределами левого поля, или необычный вывод для материала, который был обработан непреднамеренно. С тем, что я делаю, существует условие, когда внутри переменной PS1 требуется дополнительное пространство, чтобы противостоять визуальной разнице между терминалом linux и lxterm с моей установкой (Arch Bang). Без лишних пробелов терминал linux печатает первый символ приглашения в конце последней строки по какой-то причине, которую я не могу понять (конечно, это то, что я делаю, а не поведение по умолчанию). Также не могу понять, как генерировать случайный эффект (полужирный, обратный и т. Д.) Для набора символов в кавычках, так как на раннем этапе было принято решение генерировать более длинные строки для повышения производительности.
Начальный паттерн при открытии терминала
Поведение после a clear
и нажатия вводить последовательно по подсказке
наблюдения
- Должен быть переработан или модифицирован для реализации раскрашивания узоров, помимо того, чтобы делать это навалом
- Чтобы почувствовать, что идти дальше, потребуется либо поместить все это в сценарий, либо использовать более высокую форму абстракции. Но возможности терминала вполне доступны для конечного пользователя (напоминает мне «логотип»)!