Bağlam ve Soru
Terminal ve kabuk ortamını renklendirmenin birçok yolu vardır . Gibi tek tek komutları çıkış ls
ve grep
ayrıca renklendirilebilir. Doğrudan ilişkili değil, ancak yine de ilginç olanı, konsolda medya oynatma nosyonudur, ancak bu görünüşte pencereleme sisteminin üstündeki bazı çerçevelere (kütüphaneler) dayanıyor. Aşağıdaki soru sadece bash
kabuğa ve bunun Linux terminal çerçevesi ve temellerindeki uygulamasına yöneliktir .
Lütfen aşağıdaki 2B oyunda ASCII "render" montajını göz önünde bulundurun :
Bunlar rastgele oluşturulmuş sahneler değil. Seçtiğim bölümler, ASCII karakterlerini bu tür nesneleri temsil etmek için kullanan bir oyunda aslında bazı "otlak" arazilerini (ağaçlar, çalılar, çalılar, çiçekler, çimler vs.) gösteriyor. Son 4 sahnede , temelde renkli özelliklere sahip ASCII karakterlerinin remapı olan kullanıcı yapımı fayans setleri sergileniyor (bu detaylar önemsiz - bunun görseller açısından burada yapmaya çalıştığım şeyin görsel ilham kaynağı olduğunu söylemek yeterli. " Desen").
Montaj payındaki sahnelerin ortak özellikleri şunlardır:
- En fazla 5-6 farklı ASCII karakter (virgül, tırnak işareti ve birkaç diğerleri)
- 2-4 renk kullanıldı
- karakterler için
- Bazı durumlarda karakter arka planları için - son örnek, desen oluşturmak için çok az karakterli veya az karakterli renk tonlarının kullanıldığını göstermek içindir.
Şu anda VM'de sahip olduğum şey Arch Linux'tur ve soru dağıtıma özgü olmasa da , dosyayı özelleştirmek için belgelerine baktım /etc/bash.bashrc
. Çok sayıda açıklamanın istemin ve genel olarak tüm ön plan öğelerinin görünümünü yapılandırmaya girdiğini görebiliyorum . Arka plan için herhangi bir yapılandırma hakkında, bu ayarlar ve ipuçları gibi genellikle düz bir renk haricinde çok az bilgi vardır :
# 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
Konsolu kullandığımda yazmadığım boş / boş / arkaplan "boşlukları" yani kavramsal olarak ne anlama geliyorlar? sözde. Özellikle istekte bulunmayan ve yankılanan komutları saranlar. Aktif hat üzerinde ne olduğu ile ilgili olarak, bash
"hat yönelimli" bir şekilde hareket ettiğini ve bazı işlemlerin aktif hattın bir temizliğini tetiklediğini ( for i in $(seq 1 $(expr $(tput lines) \* $(tput cols))); do echo -n M; done; tput cup 15 1
sonra istemde bir karakter yazıp geri aldığınızı) göstermek mümkündür. (bir katkıda bulunan) - bunun kapsamı bir CLI’den diğerine yani zsh’e kadar değişebilir. Dahası, \[\033[44m\]
PS1 hattımdaki gibi bir şey eklediğimde bash'ı bash.bashrc
yeniden yükledikten sonra mavi bir arka plan elde ediyorum - yani belli ki bazıBurada, arka plan söz konusu olduğunda çıktı görüntüsünün üzerinde kaldıraç .
Ancak bash'in, TTY alt sistemi biçimindeki başka bir tesise dayanarak bir şeyleri ekrana getirmek için kullandığı bir yazılım olduğunu da biliyorum - ve bu, oradan, sanırım çekirdeğindeki VT bileşenine kadar iniyor . pstree -Ap
Arch on ve ardından systemd
bağlı gösterir .login
bash
Arch Linux dağıtımı dayanır agetty
TTY hizmetleri için. Basit echo $TERM
olan, kullanımda olan terminalin tipini verecektir (burada herhangi bir DE'nin dışında "linux") ve infocmp[-d spec1 spec2]
parametresiz komut, terminfo (5) terminal veritabanından aktif terminal yeteneklerini ve profil bilgilerini gösterir :
# 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,
Durduğu gibi, birçok çerçeveden terminal çerçevesinden yararlanılabilir ve temelde PS1 değişkenini ayarlayarak istemi özelleştirildiği sürece bash.bashrc yapılandırma dosyasında gösterilen özelliklerdir. Kontrol ve kaçış dizileri , imleci hareket ettirmek ve terminal bilgi veritabanında açıklanan diğer yetenekler dahil olmak üzere, işlevleri sağlamak için terminalde görüntülenen karakter akışını temel olarak kesmek için kullanılır. Bu işlevlerin çoğu, iyi bilinen ESC[
(veya \ 33) Kontrol Dizisi İntrodüseri ( burada ve burada daha fazla dizi ve bazı örnekler ) kullanılarak iletilir . Ayrıca, kullanmak da mümkündürtput
bazı terminal özelliklerini değiştirmek için doğrudan CLI'ye yarar; örneğin tput setab 4
, mavi bir arka plan üzerinde basho yankı komutları olacaktır.
Biz ise strace bash
biz eylem çıkış sıralarını ve davranışlarını hem görebilirsiniz:
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
Bu, soru için bağlam sağlar . Bir terminaldeki boş alanlar / arka plan rengi, rastgele (ama güzel) bir ASCII karakter kümesiyle değiştirilebilir mi? ancak özelliklerin nasıl uygulanacağı veya terminalde aradıklarım hakkında hiçbir fikrin yok.
Bu yüzden, eğer bu mümkün olsaydı, nihai sonucun nasıl görünebileceğinin bir örneği olarak kaba bir mockup yarattım (ciddi olarak değil :):
Temel olarak, terminaldeki bütün "boş alanlar", desen ile doldurulacaktır (burada yukarıdan bir görüntüyü "kiremiyorum", ancak gerçek uygulamada, her "boş" kümesinin rastgele oluşturulabilmesini istiyorum. 5-6 karakter ve montajda belgelenen özellikler belirtilecektir. Aktif komut satırı için farklı bir desen var, yani dalgalı "su" ama çizginin mavi olması için razı olmuştum. Bunun hayal edildiği gibi, komutlar aktif satırda yazdıkça “suyu” “silerdi” ve tabii ki bir kısıtlama karakter karakterinin CLI tarafından asla yorumlanmaması, aksi takdirde yararsız hale gelmesiydi.
Bu nedenle, bash
uygun terminal terminalinde veya içinde maruz kalan herhangi bir konfigürasyon veya arka plan için biraz rastgele bir desen oluşturacak şekilde terminaldeki bash çıktısını değiştirmek için bir dizi karakter ve renklerin kontrolünü kullanmaya izin verecek bir komut dosyası var mı? (yukarıda gösterdiklerime benzer olurdu)? Ya da sadece gibi tam desen resim sunmaya çalışıyor gibi bir şey razı olmalıdır tty arka ?
Uygulamalar
0,1 - PatternOTD sürümü (giriş yaptığınızda bir atış)
.Bashrc dosyama eklediğim aşağıdaki ifade, araştırdığımız bazı kavramları bir araya getiriyor ve standart linux terminalindeki görseller için (çok) temel bir konsept kanıtı oluşturuyor:
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
Gözlemler
- Belli ki sadece bir komut öyle ısrarcı değil, yani komutlar yazılırken uzaklaşıyor
- Karakter yani ayrı ayrı seçimi rastgele değil seçen
head -c 1
iletput cols
çok yavaş olduğu için - alıntılanan seçimden bireysel rasgele karakter yazdırmak hangi ile başlayan satırları çarparak.random
Uzun bir tamsayı (tput cols) oluşturduğunu sanmıyorum ama yine de daha hızlı. Tabii ki bu hepsi çok israf var ama işe yarıyor. - Her bir karakterin tek tek renderlenmesi / işlenmesi çok yavaş olduğundan, karakter başına veya renk için herhangi bir renk veya efekti rastgele seçmedim, çünkü yeşil renk dışında. Re: framebuffer?
- Desenin CLI tarafından yorumlanmaması anlamında CLI kullanımına müdahale etmediğini görmekten mutluyum! (neden açıklayamadığım halde)
- Su çok hızlı gitti! ;-)
0,2 - PROMPT_COMMAND iş hack
PROMPT_COMMAND değişkeninin değeri , Bash her bir birincil istemi basmadan hemen önce incelenir. Genellikle değişkeni ekrandan vb. Öğelerini işleyebileceğiniz bir betiği çağırmak için kullanacağınızı biliyorum, ancak bunu doğrudan .bashrc dosyamda yapmaya çalışıyorum. Birlikte ekran her yerde şeyler işlemek gidebiliriz Başlangıçta ben çalıştırılmadan önce imleç bazı konumsal farkındalık ie uygulamak sandım (böylece tput
daha sonra bir şey kullanmadan, daha önce olduğu pozisyona geri gelmek böyle özü pozisyonuna:
stty -echo; echo -n $'\e[6n'; read -d R x; stty echo; echo ${x#??} //value is in x;x format so...
Değeri atacağım cut -f1 -d";"
. Bunu CLI'da yapabilirim, ancak bu işi PS1 / P_C değişkenlerindeki elemanlar dizisi içinde yapmak şu anda ulaşamadığım bir yerde ve PROMPT_COMMAND'a verilen komutların her satır başı dönüşünde değerlendirilmemesi mümkün değil. her seferinde yapılmasına rağmen sadece bir kez (?) (aşağıdaki gözlemlere bakınız).
Bu yüzden yapabileceğim en iyi şey, ilk sekansımı taşımak ve hem PROMPT_COMMAND hem de .bashrc'deki PS1 değişkeninin tanımına bazı komutları eklemektir. Gibi:
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
Özet olarak, P_C kullanıp kalıcı bir görsel örüntü uygulamaya çalışıyorum, yani 2 satır ekleniyor. Maalesef "su" numaramı tekrar ederken, yani aktif çizgiyi maviye sahip (bu sadece arka plan rengini değiştiriyor, net bir çizgi yapıyor, ardından arka planı siyaha çeviriyor) iken, bu deseni oluşturmayı başaramıyorum. Bunun nasıl bir araya geldiğini göstermek için bir resim hazırladım:
Gözlemler
- Bir satırda geri almayı kullanmak, net satır davranışını tetiklemeye devam eder ve mavi
- Enter tuşuna her basıldığında, yeni aktif satırdan önce 2 satır kalıbımız vardır.
- Tabii ki, fazladan satırlara rağmen daha da aşağıya gördüğümüz gibi, komutları yan tarafa yerleştirmiyoruz.
ls
- / dev / urandom'un rasgeleliği burada P_C'de çağrıldığında rastgele görünmüyor. Bu görüntü 2 görüntüden oluşur, ancak ekstra 2 çizgi deseninin her zaman aynı olduğunu, yani her enter tuşuna basıldığında rastgelelığın üretilmediğini, ancak iki satırın her biri için yalnızca bir kez - muhtemelen yalnızca ilkini alması kolaydır. zaman .bashrc tarafından okunur
bash
. - PS1 değişkeninin içeriği şu şekilde başlar
$(echo -en '\n') $(tput setab 4)
- peki ortadaki boşluk, $ (tput ...) 'dan hemen önce, bunun çalışması için orada olması GEREKİR. Aksi halde mavi çizgi istemin üzerinde görünür ve önünde görünmez ve bunu çözemem. Ve bu kesmek, adını 0.2'ye veren şey. :)
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 ile yapılan şey, bilgi isteminin oluşturulmasından önce her seferinde 3 satır desenin basılmasıdır - ve bu 3 desen seti, 0.2'de açıklanan kısıtlamalar içinde ayrı ayrı üretilir - su için 1 karakterden ibarettir ama yine de. Daha sonra iki satır yukarı çıkacağız (kullanarak tput cuu 2
) ve istem PS1'e göre orta satırda üretiliyor. Terminalde oturum açtığımızda sadece bir kez çalıştırılan .bashrc yükündeki tam ekran deseni için ilk komut setimiz var. Şimdi, geri dönüş vagonunda her zaman tekrarlanan kendi mavi desenine sahip aktif çizginin çevresinde bir miktar dolgu var. PS1 değişkeninin ve P_C'nin içeriği dezenfekte edildi. Kaçış dizilerinin sözdizimi ve uzun zaman içinde gömülü olan renk kodlamasıecho
dizileri zor olabilir. Hatalar garip terminal davranışına yol açarbirbirlerinin üzerine yazılan satırlar, sol kenar boşluğundan veya olağandışı çıktıdan istenmeyen bir şekilde işlenen öğelere uzak görünen bir bilgi istemi içerir. Yaptığım şeyle ilgili bir koşul var, PS1 değişkeni içinde, linux terminali ile lxterm arasındaki görsel farkı ayırt etmek için kurulumumla (Arch Bang) bir ekstra alan gerekli. Fazladan boşluk olmadan, linux terminali istemenin ilk karakterini son satırın sonunda bir nedenden dolayı anlayamıyorum (tabii ki yaptığım ve varsayılan davranışı değil). Ayrıca, performansı arttırmak için daha uzun karakter dizileri oluşturmaya erken karar verildiğinden, tırnak işaretleri içinde karakter kümesinde rastgele bir etkinin (kalın, ters vb.) Nasıl üretileceğini çözemez.
Terminal açıldığında ilk desen
A clear
ve tuşuna basıldıktan sonraki davranış , komut istemine art arda girin.
Gözlemler
- Desenleri toplu olarak yapmanın ötesinde renklendirme uygulamak için yeniden tasarlanmalı veya değiştirilmelidir
- Daha ileriye gitmeyi hissetmeye başlamak, ya hepsini bir betiğe eklemeyi ya da daha yüksek bir soyutlama biçiminden yararlanmayı gerektirecektir. Ancak terminal yetenekleri son kullanıcı için oldukça olanak sağlıyor (bana "logo" u hatırlatıyor)!