Verwenden Sie Variablen zum Speichern von Terminal-Farbcodes für PS1?

33

In meinem verwende .bashrcich ANSI-Terminal-Farbcodes, um verschiedene Bits einzufärben. Es sieht aus wie das:

PS1='\u@\h:\w\[\033[33m\]$(virtual_env)\[\033[32m\]$(git_branch)\[\033[0m\]$ '

where virtual_envund git_branchare bash Funktionen, die Sachen auf stdout ausgeben.

Um das Lesen und Ändern zu vereinfachen, möchte ich die Farbcodes in Variablen speichern und auf sie verweisen, anstatt sie direkt in sie einzubetten PS1. Ich habe also eine Reihe von Variablen wie diese:

GREEN="\[\033[32m\]"
YELLOW="\[\033[33m\]"
RESET="\[\033[0m\]"

Ich möchte in der Lage sein, etwas zu schreiben wie:

PS1='\u@\h:\w${YELLOW}$(virtual_env)${GREEN}$(git_branch)${RESET}$ '

Dies funktioniert jedoch nicht - die Farbcodes werden in der Eingabeaufforderung angezeigt, als wären sie ausgeblendet. Die Farben korrekt funktionieren , wenn ich doppelte Anführungszeichen verwenden , anstatt für PS1, aber dann die Aufforderung nur ändert , wenn ich tun source ~/.bashrc.

Ich habe andere Dinge habe ich versucht , Menschen zu tun habe gesehen - mit printf, Apostrophe für die Farben, die setzen \[und \]in PS1anstelle der Farbe variabel, aber nichts scheint zu funktionieren.

Wie kann ich Variablen für die Farbcodes verwenden?

Ismail Badawi
quelle
Können Sie uns Ihre geben .bashrc?
Cuonglm
@cuonglm Gehören alle deine .bashrc uns? Ich werde mich zeigen.
CivFan

Antworten:

20

Die Lösung besteht darin, die Shell zu veranlassen, die Farbvariablen beim Definieren der Eingabeaufforderung zu ersetzen, nicht jedoch die Funktionen. Verwenden Sie dazu die doppelten Anführungszeichen, wie Sie es ursprünglich versucht haben, aber schließen Sie die Befehle, damit sie erst ausgewertet werden, wenn die Eingabeaufforderung angezeigt wird.

PS1="\u@\h:\w${YELLOW}\$(virtual_env)${GREEN}\$(git_branch)${RESET}$ "

Beachten Sie das \vor dem $()auf jedem Befehl.

Wenn wir dies wiederholen, sehen wir:

echo "$PS1"
\u@\h:\w\[\033[33m\]$(virtual_env)\[\033[32m\]$(git_branch)\[\033[0m\]$ 

Wie Sie sehen, wurden die Farbvariablen ersetzt, nicht jedoch die Befehle.

Patrick
quelle
1
Dies scheint nicht zu funktionieren, wenn $ (git_branch) ebenfalls versucht, mit $ {YELLOW} usw. zu drucken. In diesem Abschnitt allein erhalten Sie immer noch alle [] -Zeichen.
WB Reed
7

Das Problem ist, dass Ihre Variable GREENdie Literalzeichenfolge enthält, die aus "Backslash-Klammer Backslash Null Drei Drei" usw. besteht. Es enthält beispielsweise kein ASCII-Escapezeichen, das erforderlich ist, damit Ihr Terminal die Farbe ändert.

Sie können Steuerzeichen manuell in GREEN(und YELLOWund RESET) einfügen. Eine viel bessere Option ist jedoch, sie tputzuerst zu verwenden, damit Sie nichts fest codieren müssen und jeden Terminaltyp unterstützen.

GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
RESET="$(tput setaf 0)"

Der Grund, warum es Welt ist, wenn Sie "Backslash 0, 3, 3" usw. ... direkt einfügen, PS1ist, dass die Interpretation bestimmter Backslash-Sequenzen ein Merkmal der Bash-Eingabeaufforderung ist (siehe Abschnitt PROMPTING im Handbuch). Diese Ersetzung erfolgt vor der Parametererweiterung, Befehl Ersetzen, arithmetische Erweiterung und Entfernen von Anführungszeichen werden jedoch nicht auf die Ergebnisse all dieser anderen Operationen angewendet.

Celada
quelle
5
Wenn es auf diese Art und Weise zu tun, müssen Sie die Farbvariablen in einzuwickeln \[\]innerhalb der $PS1. Zum Beispiel: PS1='\u@\h:\w\[${YELLOW}\]'. Wenn Sie dies nicht tun und am Ende einen langen Befehl erhalten, der in die nächste Zeile übergeht, treten alle möglichen Probleme auf. Die Shell verwendet das \[\]Symbol, um zu bestimmen, welche Zeichen nicht druckbar sind, sodass sie bei der Berechnung der Eingabeaufforderungslänge nicht berücksichtigt werden. Dies ist erforderlich, damit die Linie ordnungsgemäß gezeichnet werden kann, wenn sie die Klemmenbreite überschreitet.
Patrick
Ich wusste nicht tput, danke. Ich werde Patricks Antwort vorerst verwenden, aber ich werde es noch einmal überprüfen, wenn ich die Gelegenheit dazu bekomme.
Ismail Badawi
2

Ändern Sie die Art und Weise, wie Sie $ GREEN, $ YELLOW und $ RESET füllen:

GREEN="$(echo -e "\033[32m")"
YELLOW="$(echo -e "\033[33m")"
RESET="$(echo -e "\033[0m")"

PS1='\u@\h:\w${YELLOW}$(virtual_env)${GREEN}$(git_branch)${RESET}$ '
Cyrus
quelle
1
Dies entspricht genau der Antwort von Celada. Celada's ist jedoch portabler, wenn das Terminal unterschiedliche Escape-Codes für die Farbeinstellung verwendet. Es wird auch dasselbe Problem mit der mehrzeiligen Aufforderungssache geben.
Patrick
2
Das \[…\]Bit muss in der Eingabeaufforderung bleiben, Sie können es nicht in eine Variable einfügen. Sie haben es vollständig entfernt, was zu Anzeigeproblemen führt (der Cursor befindet sich nicht an der Position, an der bash es erwartet).
Gilles 'SO - hör auf böse zu sein'
Abgesehen von @Patrick-Bedenken ist echo -e nicht portierbar.
Hilfemethode
1
Nicht-Portabilität tput setafbringt mehr Funktionen mit sich - lässt Sie nicht aus den "hellen" Farben auswählen, z. B. "helles Cyan". @ Cyrus Antwort tut es jedoch.
CivFan