Kontext und Frage
Es gibt viele Möglichkeiten, die Terminal- und Shell-Umgebung einzufärben . Die Ausgabe einzelner Befehle wie ls
und grep
kann auch eingefärbt werden. Nicht direkt verwandt, aber dennoch interessant ist der Gedanke , Medien an der Konsole abzuspielen. Dies scheint jedoch auf einem Framework (Bibliotheken) zu beruhen, das über dem Fenstersystem liegt. Die folgende Frage richtet sich ausschließlich nach der bash
Shell und ihrer Implementierung im Linux-Terminal-Framework und ihren Grundlagen.
Bitte beachten Sie die folgende Montage von ASCII "Renderings" einer Szene in einem 2D- Spiel :
Dies sind keine zufällig generierten Szenen. Die Segmente, die ich alle ausgewählt habe, zeigen tatsächlich eine Form von "Grasland" -Gelände (Bäume, Büsche und Sträucher, Blumen, Gras usw.) aus einem Spiel, das ASCII-Zeichen verwendet, um solche Objekte darzustellen. Die letzten 4 Szenen zeigen vom Benutzer erstellte Kachelsets, die im Grunde genommen eine Neuzuordnung von ASCII-Zeichen mit Farbspezifikationen darstellen (solche Details sind trivial - es genügt zu sagen, dass dies die visuelle Inspiration für das ist, was ich hier in Bezug auf Grafik und " Muster").
Die allgemeinen Merkmale dieser Szenen in der Montagefreigabe sind:
- Höchstens 5-6 verschiedene ASCII-Zeichen (Kommas, Anführungszeichen und einige andere)
- 2-4 Farben verwendet
- für die Charaktere
- in einigen Fällen für die Zeichenhintergründe - das letzte Beispiel zeigt die Verwendung von Farbschattierungen mit wenig oder keinem Zeichen, um ein Muster, dh ein Farbmosaik, zu erstellen
Was ich im Moment in einer VM habe, ist Arch Linux, und obwohl die Frage nicht verteilungsspezifisch ist, habe ich in deren Dokumentation nachgeschlagen, um die /etc/bash.bashrc
Datei anzupassen . Ich kann sehen, dass viele Erklärungen in die Konfiguration des Erscheinungsbilds der Eingabeaufforderung und allgemein aller Vordergrundelemente einfließen. Es gibt nur wenige Informationen zu einer Konfiguration für den Hintergrund, außer normalerweise für eine Volltonfarbe, wie z. B. folgende Einstellungen und Tipps :
# 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
Ich verstehe konzeptionell immer noch nicht, woraus diese leeren / leeren / Hintergrund- "Leerzeichen" bestehen, die ich bei der Verwendung der Konsole nicht eingegeben habe, z. B. "Woraus bestehen sie?" sozusagen. Besonders diejenigen, die nicht an der Eingabeaufforderung stehen und die Befehle, die zurückgegeben werden, umschließen. In Bezug auf das, was auf der aktiven Leitung passiert, ist es möglich zu demonstrieren, dass sich bash
die Leitung "zeilenorientiert" verhält und dass einige Vorgänge das Löschen der aktiven Leitung auslösen ( for i in $(seq 1 $(expr $(tput lines) \* $(tput cols))); do echo -n M; done; tput cup 15 1
dann geben Sie an der Eingabeaufforderung ein Zeichen ein und drücken Sie die Rücktaste - demonstriert) ein Mitwirkender) - dessen Ausmaß von einer CLI zu einer anderen variieren kann, dh zsh. Darüber hinaus scheint es , wenn ich so etwas wie hinzufügen , \[\033[44m\]
um meine PS1 Linie in bash.bashrc
ich einen blauen Hintergrund nach dem erneuten Laden bash bekommen - so offensichtlich weiß ich , dass es einigeHebel hier über das Erscheinungsbild der Ausgabe in Bezug auf den Hintergrund .
Ich weiß aber auch, dass bash eine Software ist, die sich auf eine andere Funktion in Form des TTY-Subsystems stützt, um die Dinge auf den Bildschirm zu bringen - und das geht von dort bis zur VT-Komponente im Kernel, wie ich annehme. pstree -Ap
auf Arch-Shows, die systemd
mit login
und dann mit verknüpft sind bash
.
Die Arch Linux- Distribution verwendet agetty
TTY-Dienste. Ein einfacher Befehl echo $TERM
liefert den verwendeten Terminaltyp ("linux" hier außerhalb eines DE) und der infocmp[-d spec1 spec2]
Befehl ohne Parameter zeigt die aktiven Terminalfähigkeiten und Profilinformationen aus der Terminaldatenbank terminfo (5) an :
# 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,
Gegenwärtig können viele Funktionen über das Terminal-Framework genutzt werden. Grundsätzlich sind dies die Funktionen, die in der bash.bashrc-Konfigurationsdatei verfügbar gemacht werden, sofern die Eingabeaufforderung durch Festlegen der PS1-Variablen angepasst wird. Steuerungs- und Escape-Sequenzen werden verwendet, um den im Terminal angezeigten Zeichenfluss grundsätzlich zu unterbrechen, um Funktionen bereitzustellen, einschließlich des Bewegens des Cursors und anderer in der Terminalinformationsdatenbank beschriebener Funktionen. Viele dieser Funktionen werden mit dem bekannten ESC[
(oder \ 33) Control Sequence Introducer übergeben (mehr Sequenzen hier und hier und einige Beispiele ). Weiterhin ist es auch möglich, die zu verwendentput
Dienstprogramm direkt auf der CLI zum Ändern einiger Terminal-Eigenschaften; Zum Beispiel tput setab 4
werden Bash-Echo-Befehle auf blauem Hintergrund angezeigt.
Wenn wir strace bash
sowohl die Escape-Sequenzen als auch das Verhalten in Aktion sehen können:
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
Dies bietet Kontext für die Frage Kann die leere Fläche / Hintergrundfarbe in einem Terminal durch einen zufälligen (aber hübschen) Satz von ASCII-Zeichen ersetzt werden? gibt aber keine ahnung, wie die funktionen zu implementieren sind oder wonach ich im terminal suche.
Deshalb habe ich ein grobes Modell erstellt, um zu veranschaulichen, wie das Endergebnis aussehen könnte, wenn dies möglich wäre (nein im Ernst :):
Grundsätzlich wäre der gesamte "leere Raum" im Terminal mit dem Muster gefüllt (hier "kachele" ich eines der Bilder von oben, möchte aber in der tatsächlichen Implementierung für jedes einzelne "Rohling" zufällig aus dem Satz von erzeugt werden 5-6 Zeichen und Merkmale aus der Montage dokumentiert, die angegeben werden würde). Es gibt ein anderes Muster für die aktive Befehlszeile, dh welliges "Wasser", aber ich würde mich damit begnügen, dass die Zeile blau ist. So wie man es sich vorgestellt hat, würden Befehle das "Wasser" "löschen", wenn sie in die aktive Zeile eingegeben werden, und natürlich würde eine Einschränkung darin bestehen, dass das Zeichenmuster von der CLI niemals interpretiert wird, da es sonst unbrauchbar wird.
Gibt es also eine Konfiguration, die im bash
oder im eigentlichen Terminal-Framework verfügbar ist, oder ein Skript, mit dem eine Reihe von Zeichen und eine gewisse Kontrolle über die Farben verwendet werden können, um die Ausgabe von bash im Terminal so zu ändern, dass ein etwas zufälliges Muster für den Hintergrund generiert wird? (Was wäre ähnlich wie das, was ich oben gezeigt habe)? Oder sollte ich mich einfach damit begnügen, ein vollständiges Musterbild als Hintergrund für das tty bereitzustellen ?
Implementierungen
0.1 - PatternOTD Version (One Shot Deal wenn Sie sich einloggen)
Der folgende Ausdruck, den ich meiner .bashrc-Datei hinzugefügt habe, fasst einige der von uns untersuchten Begriffe zusammen und stellt einen (sehr) grundlegenden Proof-of-Concept für die visuellen Elemente im Standard-Linux-Terminal dar:
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
Beobachtungen
- Es ist offensichtlich nur ein Befehl, der nicht permanent ist, dh er verschwindet, wenn Befehle eingegeben werden
- Entschied sich nicht individuell auf die Auswahl Randomisierung von Zeichen , dh
head -c 1
mit dertput cols
die Linien multipliziert mit zu beginnen, die einzelnen zufälligen Zeichen aus der angegebenen Auswahl drucken würde - weil es zu langsam ist. Ich glaube nicht, dass esrandom
eine (tput cols) lange Ganzzahl erzeugt, aber es ist immer noch schneller. Sicher ist das alles sehr verschwenderisch, aber es funktioniert. - Es wurden keine Farben oder Effekte pro Zeichen oder auf andere Weise zufällig ausgewählt, mit Ausnahme des Grüns, da, wie ich erklärt habe, jedes Zeichen einzeln zu langsam gerendert / verarbeitet wird. Re: Framebuffer?
- Es freut mich zu sehen, dass das Muster die CLI-Nutzung nicht in dem Sinne beeinträchtigt, dass es von der CLI nicht interpretiert wird! (Warum, obwohl ich es nicht erklären konnte)
- Wasser ist zu schnell weg! ;-)
0.2 - PROMPT_COMMAND Hack Job
Der Wert der Variablen PROMPT_COMMAND wird geprüft, unmittelbar bevor Bash jede primäre Eingabeaufforderung druckt. Ich weiß, dass Sie normalerweise die Variable verwenden würden, um ein Skript aufzurufen, in dem Sie Elemente aus der Anzeige usw. verarbeiten könnten, aber ich versuche eher, dies direkt in meiner .bashrc-Datei zu tun. Anfangs dachte ich , ich könnte einiges Positions Bewusstsein dh implementieren , wo der Cursor vor der Ausführung ist (so dass ich mit auf dem Bildschirm überall machen Dinge gehen könnte tput
dann in die Position zurückkommen ich vorher war, etwas mit , wie diese Position zu extrahieren:
stty -echo; echo -n $'\e[6n'; read -d R x; stty echo; echo ${x#??} //value is in x;x format so...
Ich würde den Wert an leiten cut -f1 -d";"
. Ich kann dies auf der CLI ausführen, aber die Ausführung dieser Funktion innerhalb der Elementsequenz in den PS1 / P_C-Variablen ist derzeit nicht in meiner Reichweite und es ist möglich, dass der in PROMPT_COMMAND eingegebene Befehl nicht bei jedem Wagenrücklauf ausgewertet wird, sondern bei jedem Wagenrücklauf nur einmal (?), obwohl sie jedes Mal ausgeführt werden (siehe Anmerkungen unten).
Das Beste, was ich tun kann, ist, meine ursprüngliche Sequenz zu übertragen und einige Befehle sowohl für PROMPT_COMMAND als auch für die Definition der PS1-Variablen in .bashrc hinzuzufügen. Wie so:
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
Zusammenfassend verwende ich P_C, um zu versuchen, ein dauerhaftes visuelles Muster zu implementieren, dh es werden 2 Zeilen hinzugefügt. Leider gelingt es mir nicht, beide Muster zu erstellen, während ich meinen "Wassertrick" wiederhole, dh die aktive Linie blau habe (die nur die Hintergrundfarbe ändert, eine klare Linie macht und dann den Hintergrund wieder in schwarz ändert). Ich habe ein Bild zusammengestellt, um zu zeigen, wie das zusammenspielt:
Beobachtungen
- Die Verwendung der Rücktaste in einer Zeile löst immer noch das Verhalten einer klaren Linie aus und das Blau ist verschwunden
- Bei jedem Drücken der Eingabetaste stehen 2 Musterzeilen vor der neuen aktiven Zeile
- Natürlich wird, wie wir weiter unten sehen, trotz der zusätzlichen Zeilen das Muster nicht auf die Seite der Befehle wie z
ls
- Die Zufälligkeit von / dev / urandom scheint hier in P_C nicht so zufällig zu sein. Dieses Bild besteht aus 2 Bildern, aber es ist leicht zu erkennen, dass das Muster mit den zusätzlichen 2 Zeilen immer gleich ist, dh die Zufälligkeit wird nicht bei jedem Tastendruck erzeugt, sondern nur einmal für jede der beiden Zeilen - möglicherweise nur für die erste Zeit .bashrc wird gelesen von
bash
. - Der Inhalt der PS1-Variablen beginnt mit
$(echo -en '\n') $(tput setab 4)
- nun, dieser Platz in der Mitte, kurz vor $ (tput ...), MUSS da sein, damit dies funktioniert. Andernfalls wird die blaue Linie über der Eingabeaufforderung und nicht davor angezeigt, und das kann ich nicht beheben. Und dieser Hack gibt 0.2 seinen Namen. :)
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\]"
Mit PROMPT_COMMAND werden jedes Mal 3 Musterzeilen gedruckt, bevor die Eingabeaufforderung generiert wird - und diese 3 Mustersätze werden innerhalb der in 0.2 erläuterten Einschränkungen einzeln generiert - ohne Bedeutung für das Wasser, da es 1 Zeichen, aber immer noch ist. Dann gehen wir zwei Zeilen hoch (mit tput cuu 2
) und die Eingabeaufforderung wird in der mittleren Zeile gemäß PS1 generiert. Wir haben immer noch unseren anfänglichen Befehlssatz für das Vollbildmuster unter .bashrc load, der nur einmal ausgeführt wird, wenn wir uns beim Terminal anmelden. Jetzt haben wir ein paar Abstände um die aktive Linie, die ein eigenes blaues Muster hat, das sich immer wiederholt, wenn es einen Rücklaufwagen gibt. Der Inhalt der PS1-Variablen und des P_C wurde bereinigt. Die Syntax der Escape-Sequenzen und die Farbcodierung sind in long eingebettetecho
Sequenzen können schwierig sein. Fehler führen zu merkwürdigem TerminalverhaltenDazu gehören Zeilen, die sich gegenseitig überschreiben, eine Eingabeaufforderung, die nicht am linken Rand angezeigt wird, oder ungewöhnliche Ausgaben für unbeabsichtigte Vorgänge. Es besteht eine Bedingung für das, was ich tue. In der PS1-Variablen ist ein zusätzlicher Platz erforderlich, um einen visuellen Unterschied zwischen dem Linux-Terminal und lxterm mit meinem Setup (Arch Bang) auszugleichen. Ohne das zusätzliche Leerzeichen gibt das Linux-Terminal das erste Zeichen der Eingabeaufforderung am Ende der letzten Zeile aus einem Grund aus, den ich nicht herausfinden kann (das ist natürlich etwas, was ich tue, und nicht das Standardverhalten). Ich kann auch nicht herausfinden, wie ein zufälliger Effekt (fett, invers usw.) auf die Menge der Zeichen in Anführungszeichen erzeugt werden kann, da frühzeitig entschieden wurde, längere Zeichenfolgen zu generieren, um die Leistung zu steigern.
Anfangsmuster beim Öffnen des Terminals
Verhalten nach a clear
und Drücken der Eingabetaste nacheinander an der Eingabeaufforderung
Beobachtungen
- Sollte überarbeitet oder modifiziert werden, um das Einfärben der Muster über die Massenproduktion hinaus zu implementieren
- Wenn Sie anfangen zu spüren, dass es viel weiter geht, müssen Sie entweder alles in ein Skript schreiben oder eine höhere Form der Abstraktion einsetzen. Aber die Terminal-Fähigkeiten sind für den Endbenutzer ziemlich aktiv (erinnert mich an "Logo")!
Antworten:
0.5a - Cyan Tumbleweed Plains
Die früheren Implementierungen, die mit der Frage versehen sind, beruhen auf einer Folge von Befehlen, die verwendet werden,
tr
und einem Satz von Einzelbytezeichen. Wie in dieser Frage und Antwort erläutert , kann das Dienstprogramm keine Multibyte-Zeichen wie Unicode verarbeiten. Die Nutzung dieser Charaktere war jedoch sehr wichtig, um den gewünschten Effekt zu erzielen. Es wurde eine "Lösung" bereitgestellt, die es ermöglicht, die Einzelbyte- und Mehrbyte-Zeichen zum Rendern in einem einzigen Stream zu mischen. Die dort entwickelte Lösung wird hier vorgestellt und angepasst:Diese Implementierung rendert nicht mehr pro Zeile, sondern druckt die gesamte Sequenz am Ende der
sed
Verarbeitung auf einmal. Dies erscheint nur beim Login einmalig oder generell beimbash
Start. Hier ist ein solches zufälliges Muster beim Start (wir können zwei Grüntöne und zwei Blautöne sehen):Die Bildschirme zeigen das Ergebnis im Standard-Linux-Terminal und es funktioniert auch in xterm. Ich habe einige dieser neuen Musterzeichen in der PS1-Eingabeaufforderung verwendet, während sich PROMPT_COMMAND nur um die aktive Zeile und deren 2-Zeilen-Auffüllung kümmert, die 1-Byte-Zeichen verwenden.
Das Muster passt auch gut zu meiner aktuellen Distribution, die
archbey
.bashrc aufruft:Es ist in für Weihnachten! Prost Leute :)
quelle
aafire
zum Beispielaafire -driver curses -extended -gamma 1 -floyd_steinberg -random 5
für ein warmes Intro.Die Anzeige wird vom Terminal verwaltet, eine Software, die wie ein Webbrowser funktioniert: Sie interpretiert Zeichenfolgen zum Einstellen der Anzeige (siehe man-Terminfo ). Die Bash-Shell teilt dem Terminal nicht mit, wie der leere Bereich des Bildschirms ausgefüllt werden soll.
Einige Terminals können Bilder als Hintergrund haben, wie z. B. gterm, aber es wird nicht von der Shell erstellt.
quelle