Contexte et question
Il existe de nombreuses façons de coloriser l' environnement du terminal et du shell. La sortie des commandes individuelles, telles que ls
et grep
, peut également être colorisée. La notion de jouer des médias sur la console n'est pas directement liée mais intéressante, mais cela s'appuie apparemment sur un cadre (bibliothèques) au-dessus du système de fenêtrage. La question suivante concerne uniquement le bash
shell et son implémentation dans le cadre du terminal Linux et ses fondements.
Veuillez considérer le montage suivant des "rendus" ASCII d'une scène dans un jeu 2D :
Ce ne sont pas des scènes générées aléatoirement. Les segments que j'ai sélectionnés représentent tous en fait une forme de terrain de «prairie» (arbres, buissons et arbustes, fleurs, herbe, etc.) d'un jeu qui utilise des caractères ASCII pour représenter de tels objets. Les 4 dernières scènes présentent des ensembles de tuiles créés par l'utilisateur qui sont essentiellement un remappage de caractères ASCII avec des spécifications de couleurs (ces détails sont triviaux - il suffit de dire que c'est l'inspiration visuelle pour ce que j'essaie d'accomplir ici en termes de visuels et " modèle").
Les caractéristiques communes de ces scènes dans le partage de montage sont les suivantes:
- 5-6 caractères ASCII différents au maximum (virgules, guillemets et quelques autres)
- 2-4 couleurs utilisées
- pour les personnages
- pour les arrière-plans de caractères dans certains cas - le dernier exemple est là pour montrer l'utilisation de nuances de couleur avec peu ou pas de caractère pour créer un motif, c'est-à-dire une mosaïque de couleurs
Ce que j'ai en ce moment dans une machine virtuelle est Arch Linux et bien que la question ne soit pas spécifique à la distribution, j'ai examiné leur documentation pour personnaliser le /etc/bash.bashrc
fichier. Je peux voir que beaucoup d'explications entrent dans la configuration de l'apparence de l' invite et généralement de tous les éléments de premier plan. Il y a peu d'informations sur une configuration pour l'arrière-plan, sauf généralement pour une couleur unie, comme ces paramètres et conseils :
# 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
Je ne sais toujours pas conceptuellement quels sont ces "espaces" vides / vides / d'arrière-plan que je n'ai pas saisis lorsque j'utilise la console, c'est-à-dire "de quoi sont-ils faits?" pour ainsi dire. Surtout ceux qui ne sont pas à l'invite et qui encapsulent les commandes qui sont reprises. En ce qui concerne ce qui se passe sur la ligne active, il est possible de démontrer qu'il bash
agit de manière "orientée ligne" et que certaines opérations déclenchent un effacement de la ligne active ( for i in $(seq 1 $(expr $(tput lines) \* $(tput cols))); do echo -n M; done; tput cup 15 1
, puis à l'invite, tapez un caractère et retour arrière - démontré un contributeur) - dont l'étendue peut varier d'une CLI à une autre, c'est-à-dire zsh. De plus, il semble quand j'ajouter quelque chose comme \[\033[44m\]
à ma ligne de PS1 bash.bashrc
je reçois un fond bleu après rechargeant bash - donc évidemment , je sais qu'il ya un certaintirer parti ici de l'apparence de sortie en ce qui concerne l' arrière - plan .
Mais je sais aussi que bash est un logiciel reposant sur une autre fonctionnalité sous la forme du sous-système TTY pour apporter des choses à l'écran - et cela va de là au composant VT dans le noyau, je suppose. pstree -Ap
sur Arch montre systemd
lié à login
puis à bash
.
La distribution Arch Linux s'appuie sur les agetty
services TTY. Un simple echo $TERM
donnera le type de terminal utilisé ("linux" ici en dehors de tout DE) et la infocmp[-d spec1 spec2]
commande sans paramètre affiche les capacités du terminal actif et les informations de profil de la base de données du terminal 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,
Dans l'état actuel des choses, de nombreuses capacités peuvent être exploitées à partir de l'infrastructure du terminal et ce sont essentiellement les fonctionnalités qui sont exposées dans le fichier de configuration bash.bashrc dans la mesure où l'invite est personnalisée en définissant la variable PS1. Les séquences de contrôle et d'échappement sont utilisées pour interrompre fondamentalement le flux d'affichage de caractères dans le terminal afin de fournir des fonctions, y compris le déplacement du curseur et d'autres capacités décrites dans la base de données d'informations du terminal. Beaucoup de ces fonctions sont transmises en utilisant le bien connuESC[
introducteur de séquence de contrôle (ou \ 33) (plus de séquences ici et ici , et quelques exemples ). En outre, il est également possible d'utiliser letput
utilitaire directement sur la CLI pour modifier certaines propriétés du terminal; par exemple, tput setab 4
aura des commandes bash echo sur fond bleu.
Si nous , strace bash
nous pouvons voir les deux séquences d'échappement et le comportement en action:
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
Cela fournit un contexte à la question. Les espaces vides / la couleur d'arrière-plan dans un terminal peuvent-ils être remplacés par un jeu aléatoire (mais joli) de caractères ASCII? mais ne donne aucune idée de la façon de mettre en œuvre les fonctionnalités ou de ce que je recherche dans le terminal.
J'ai donc créé une maquette brute comme exemple de ce à quoi le résultat final pourrait ressembler si cela était possible (non sérieusement :):
Fondamentalement, tout "l'espace vide" dans le terminal serait rempli avec le motif (ici, je "tuile" l'une des images ci-dessus, mais je voudrais dans la mise en œuvre réelle pour chaque "blanc" individuel être généré de manière aléatoire à partir de l'ensemble de 5-6 caractères et caractéristiques documentés à partir du montage qui seraient précisés). Il y a un modèle différent pour la ligne de commande active, c'est-à-dire "l'eau" ondulée, mais je me contenterais que la ligne soit bleue. Comme cela a été imaginé, les commandes "effaceraient" l '"eau" au fur et à mesure qu'elles sont tapées sur la ligne active et bien sûr une contrainte serait que le motif des caractères ne soit jamais interprété par la CLI sinon cela le rendrait inutile.
Y a-t-il donc une configuration exposée dans bash
ou dans le cadre du terminal proprement dit, ou un script qui permettrait d'utiliser un ensemble de caractères et un certain contrôle sur les couleurs pour modifier la sortie de bash dans le terminal afin de générer un motif quelque peu aléatoire pour l'arrière-plan (qui serait similaire à ce que j'ai montré ci-dessus)? Ou devrais-je simplement me contenter de quelque chose comme essayer de fournir une image de motif complète comme arrière - plan pour le tty ?
Implémentations
0.1 - Version PatternOTD (accord unique lorsque vous vous connectez)
L'expression suivante que j'ai ajoutée à mon fichier .bashrc rassemble certaines des notions que nous avons explorées et constitue une preuve de concept (très) basique pour les visuels dans le terminal linux standard:
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
Observations
- C'est évidemment juste une commande donc pas persistante c'est à dire qu'elle défile lorsque les commandes sont tapées
- Vous avez choisi de ne pas randomiser individuellement la sélection de caractères, c'est-
head -c 1
à- dire entput cols
multipliant les lignes pour commencer, ce qui imprimerait des caractères aléatoires individuels à partir de la sélection citée - car c'est trop lent. Je ne pense pasrandom
génère un entier long (tput cols) mais c'est toujours plus rapide. Certes, tout cela est très coûteux, mais cela fonctionne. - N'a pas randomisé de couleur ou d'effet par personnage ou autrement, sauf pour ce vert car, comme je l'ai expliqué, le rendu / traitement de chaque caractère individuellement est trop lent. Re: framebuffer?
- Je suis heureux de voir que le modèle n'interfère pas avec l'utilisation de la CLI dans le sens où il n'est pas interprété par la CLI! (pourquoi bien que je ne puisse pas expliquer)
- L'eau est partie trop vite! ;-)
0.2 - Tâche de piratage PROMPT_COMMAND
La valeur de la variable PROMPT_COMMAND est examinée juste avant que Bash imprime chaque invite principale. Je sais que vous utilisez généralement la variable pour appeler un script où vous pouvez traiter des éléments de l'affichage, etc., mais j'essaie plutôt de le faire directement dans mon fichier .bashrc. Au départ, je pensais que je pouvais implémenter une certaine conscience de la position, c'est-à-dire où se trouve le curseur avant l'exécution (donc je pouvais aller rendre les choses à l'écran n'importe où avec tput
puis revenir à la position que j'étais avant, en utilisant quelque chose comme ça pour extraire la position:
stty -echo; echo -n $'\e[6n'; read -d R x; stty echo; echo ${x#??} //value is in x;x format so...
Je donnerais la valeur à cut -f1 -d";"
. Je peux le faire sur l'interface de ligne de commande, mais rendre ce travail à l'intérieur de la séquence d'éléments dans les variables PS1 / P_C est hors de ma portée pour le moment et il est possible que toute commande placée dans PROMPT_COMMAND ne soit pas évaluée à chaque retour de chariot, mais plutôt une seule fois (?) malgré l'exécution à chaque fois (voir observations ci-dessous).
Donc, le mieux que je puisse faire est de reporter ma séquence initiale et d'ajouter des commandes à la fois à PROMPT_COMMAND et à la définition de la variable PS1 dans .bashrc. Ainsi:
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
En résumé, j'utilise P_C pour essayer d'implémenter un modèle visuel persistant, c'est-à-dire que 2 lignes sont ajoutées. Malheureusement, je ne peux pas réussir à créer ces deux motifs tout en répétant mon astuce "eau", c'est-à-dire avoir la ligne active bleue (qui change simplement la couleur d'arrière-plan, fait une ligne claire, puis change l'arrière-plan en noir). J'ai mis en place une image pour montrer comment cela se joue ensemble:
Observations
- L'utilisation du retour arrière sur une ligne déclenche toujours le comportement de la ligne claire et le bleu a disparu
- Chaque fois que la touche Entrée est enfoncée, nous avons 2 lignes de motif avant la nouvelle ligne active
- Bien sûr, comme nous le voyons plus loin, malgré les lignes supplémentaires, nous n'encapsulons pas le motif du côté des commandes telles que
ls
- Le caractère aléatoire de / dev / urandom ne semble pas si aléatoire lorsqu'il est appelé ici dans P_C. Cette image est composée de 2 images, mais il est facile de comprendre que le motif de 2 lignes supplémentaires est toujours le même, c.-à-d. heure .bashrc est lu par
bash
. - Le contenu de la variable PS1 commence par
$(echo -en '\n') $(tput setab 4)
- eh bien cet espace au milieu là, juste avant $ (tput ...), il DOIT être là pour que cela fonctionne. Sinon, la ligne bleue apparaît en haut de l'invite et non en face d'elle et je ne peux pas résoudre cela. Et ce hack est ce qui donne son nom à 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\]"
Ce qui est fait avec PROMPT_COMMAND, c'est que 3 lignes de motifs sont imprimées à chaque fois avant que l'invite soit générée - et ces 3 ensembles de motifs sont générés individuellement dans les contraintes expliquées en 0.2 - sans signification pour l'eau car c'est 1 caractère mais quand même. Ensuite, nous montons deux lignes (l'utilisation detput cuu 2
) et l'invite est générée sur la ligne médiane selon PS1. Nous avons toujours notre ensemble initial de commandes pour le modèle plein écran sur la charge .bashrc qui n'est exécuté qu'une seule fois lorsque nous nous connectons au terminal. Nous avons maintenant un remplissage autour de la ligne active qui a son propre motif bleu qui se répète toujours quand il y a un chariot de retour. Le contenu de la variable PS1 et du P_C a été nettoyé. La syntaxe des séquences d'échappement et le codage couleur intégrés dans les longsecho
les séquences peuvent être délicates. Les erreurs conduisent à un comportement de terminal étrangey compris des lignes qui se remplacent, une invite qui apparaît loin de la marge gauche ou une sortie inhabituelle vers des éléments qui ont été traités involontairement. Une condition existe avec ce que je fais, où un espace supplémentaire est requis à l'intérieur de la variable PS1 pour contrer une différence visuelle entre le terminal linux et lxterm avec ma configuration (Arch Bang). Sans l'espace supplémentaire, le terminal linux affiche le premier caractère de l'invite à la fin de la dernière ligne pour une raison que je ne peux pas comprendre (bien sûr, c'est quelque chose que je fais et non le comportement par défaut). Je ne peux pas non plus comprendre comment générer un effet aléatoire (gras, inverse, etc.) sur l'ensemble de caractères entre guillemets, car il a été décidé au début de générer des chaînes plus longues pour augmenter les performances.
Schéma initial à l'ouverture du terminal
Comportement après a clear
et en appuyant sur Entrée successivement à l'invite
Observations
- Doit être repensé ou modifié pour mettre en œuvre la colorisation des motifs au-delà de le faire en vrac
- Commencer à sentir que pour aller beaucoup plus loin, il faudra soit mettre tout cela dans un script, soit tirer parti d'une forme d'abstraction plus élevée. Mais les capacités du terminal sont tout à fait habilitantes pour l'utilisateur final (me rappelle le "logo")!
Réponses:
0.5a - Plaines Cyan Tumbleweed
Les implémentations antérieures fournies avec la question reposent sur une séquence de commandes qui utilise
tr
et un ensemble de caractères à un octet. Comme cela a été expliqué dans ce Q&R , l'utilitaire ne peut pas traiter les caractères multi-octets tels que Unicode. Mais tirer parti de ces personnages était tout à fait essentiel pour obtenir l'effet souhaité. Une "solution" a été fournie qui permet de mélanger les caractères mono-octet et multi-octets dans un seul flux pour le rendu. La solution développée ici est présentée et personnalisée ici:Cette implémentation ne rend plus par ligne mais imprime plutôt la séquence entière en une seule fois à la fin du
sed
traitement. Cela n'apparaît qu'une fois lors de la connexion ou généralement lors dubash
lancement. Voici un tel motif aléatoire au lancement (nous pouvons voir deux nuances de vert et deux nuances de cyan):Les écrans montrent le résultat dans le terminal linux standard et il fonctionne également sous xterm. J'ai utilisé certains de ces nouveaux caractères de modèle dans l'invite PS1 tandis que PROMPT_COMMAND s'occupe juste de la ligne active et de son remplissage de 2 lignes qui utilisent des caractères de 1 octet.
Le modèle correspond également bien à ma distribution actuelle qui appelle
archbey
en .bashrc .:C'est pour Noël! Vive les gens :)
la source
aafire
, par exemple,aafire -driver curses -extended -gamma 1 -floyd_steinberg -random 5
pour une intro chaleureuse.L'affichage est géré par le terminal un logiciel qui fonctionne de la même manière qu'un navigateur web: il interprète les séquences de caractères pour régler l'affichage (voir man terminfo ). Le shell bash ne dira pas au terminal comment remplir la zone vide de l'écran.
Certains terminaux peuvent avoir des images en arrière-plan comme gterm mais cela n'est pas fait par le shell.
la source