Контекст і питання
Існує багато способів розфарбовування середовища терміналу та оболонки. Виведення окремих команд, таких як ls
і grep
, також може бути кольоровим. Не пов'язане безпосередньо, але цікаво, проте, це поняття відтворення медіа на консолі, але це, здавалося б, покладається на деякі рамки (бібліотеки) вгорі віконної системи. Наступне питання орієнтоване виключно на bash
оболонку та її реалізацію в термінальній системі Linux та її основах.
Будь ласка, врахуйте наступний монтаж ASCII "рендерінгу" сцени у 2D грі :
Це не випадкові породжені сцени. Вибрані нами сегменти насправді зображують певну форму "лугової" місцевості (дерева, кущі та чагарники, квіти, траву тощо) з гри, яка використовує символи ASCII для представлення таких об'єктів. Останні 4 сцени демонстрували користувачі наборів плиток, які в основному являють собою перезапис символів ASCII з кольоровими специфікаціями (такі деталі тривіальні - достатньо сказати, що це візуальне натхнення для того, що я намагаюся досягти тут у плані візуалізації та " візерунок ").
Спільними рисами цих сцен у фотомонтажі є:
- Максимум 5-6 різних символів ASCII (коми, лапки та кілька інших)
- Використовується 2-4 кольори
- для персонажів
- для фонів символів у деяких випадках - останній приклад, щоб показати використання кольорових відтінків з невеликим або відсутнім символом для створення візерунка, тобто кольорової мозаїки
Наразі у мене в VM є 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
тоді в запиті введіть char і поверніть його назад - продемонстрував дописувач) - ступінь якої може змінюватися від 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]
команда без параметра показує активні можливості терміналу та інформацію про профіль з термінальної бази терміналів (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
можемо побачити як послідовності втечі, так і поведінку в дії:
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 в терміналі, щоб створити дещо випадковий візерунок для фону (що було б схоже на те, що я показав вище)? Або я повинен просто погодитися з чимось на кшталт спроби поставити зображення повного шаблону як тло для тт ?
Впровадження
0.1 - VersionOTD-версія (одна угода для зняття під час входу)
Наступне вираження, яке я додав до свого файлу .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
Спостереження
- Це, очевидно, лише команда, настільки не стійка, тобто прокручується, коли команди набираються
- Opted не індивідуальні рандомізації вибір із символів , тобто
head -c 1
зtput cols
множенням рядків , щоб почати с, яка буде друкувати окремі випадкові символи з цитованого вибору - бо це занадто повільно. Я не думаю, щоrandom
генерує (tput cols) довге ціле число, але все ж це швидше. Звичайно, це все дуже марно, але це працює. - Не було рандомізовано жодного кольору чи ефекту на символ чи іншим чином, окрім зеленого, оскільки, як я пояснив, надання / обробка кожного символу окремо є надто повільним. Re: framebuffer?
- Я радий бачити, що модель не перешкоджає використанню 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 рядки. На жаль, мені не вдасться створити обидва ці шаблони, повторюючи свій "водний" трюк, тобто мати активну лінію синього кольору (яка просто змінює колір фону, робить чітку лінію, а потім змінює фон назад на чорний). Я зібрав зображення, щоб показати, як це грає разом:
Спостереження
- Використання зворотної області на лінії все ще запускає чітку поведінку лінії, і синій зник
- Щоразу, коли натискається клавіша введення, перед новим активним рядком ми маємо 2 рядки візерунка
- Звичайно, як ми бачимо далі вниз, незважаючи на додаткові рядки, ми не обмотуємо візерунок збоку таких команд, як
ls
- Випадковість / dev / urandom здається не такою випадковою, коли викликається тут у P_C. Це зображення складається з двох зображень, але легко зрозуміти, що додатковий шаблон 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 були дезінфіковані. Синтаксис послідовностей евакуації та кольорового кодування, вбудованих протягом довгихecho
послідовності можуть бути складними. Помилки призводять до дивної поведінки терміналіввключаючи рядки, які перезаписують один одного, підказку, яке з’являється подалі від лівого поля або незвичного виводу до матеріалів, які були оброблені ненавмисно. Існує умова в тому, що я роблю, коли всередині змінної PS1 потрібно додаткове місце, щоб протиставити візуальну різницю між терміналом Linux та lxterm моїм налаштуванням (Arch Bang). Без зайвого простору термінал Linux друкує перший символ підказки в кінці останнього рядка, чомусь я не можу зрозуміти (звичайно, це щось, що я роблю, а не поведінка за замовчуванням). Також не можна зрозуміти, як генерувати якийсь випадковий ефект (жирний, зворотний тощо) для набору символів у лапках, оскільки було вирішено рано створювати довші рядки для підвищення продуктивності.
Початкова схема, коли термінал відкриється
Поведінка після clear
натискання клавіші вводиться послідовно під запит
Спостереження
- Потрібно переробити або модифікувати, щоб реалізувати колоризацію шаблонів, а не робити це оптом
- Починаючи відчувати, що для того, щоб піти набагато далі, знадобиться або вкласти все це в сценарій, або використовувати якусь вищу форму абстракції. Але можливості терміналу цілком сприятливі для кінцевого користувача (нагадує мені про "логотип")!