Gilles hat Ihr Hauptproblem identifiziert, aber ich wollte versuchen, es anders zu erklären.
Bash interpretiert das Escape der speziellen Eingabeaufforderung nur, bevor Variablen in der Eingabeaufforderung erweitert werden. Dies bedeutet, dass die Verwendung \e
in einer Variablen, die über die Eingabeaufforderung erweitert wird, nicht funktioniert, obwohl sie direkt in funktioniert PS1
.
Dies funktioniert beispielsweise wie erwartet und enthält roten Text:
PS1='\e[1;31m this is in red '
Dies ist jedoch nicht der Fall, sondern setzt nur ein Literal \e
in die Eingabeaufforderung:
RED='\e[1;31m'
PS1="$RED not in red "
Wenn Sie die Farb-Escapezeichen in Variablen speichern möchten, können Sie mit ANSI-C-Anführungszeichen ( $'...'
) ein Literal-Escape-Zeichen in die Variable einfügen.
Dazu können Sie Ihre Definition von GREEN
, RED
und ändern NONE
, sodass ihr Wert die tatsächliche Escape-Sequenz ist.
GREEN=$'\033[1;32m'
RED=$'\033[1;31m'
NONE=$'\033[m'
Wenn Sie das tun, sollte Ihr erstes PS1
mit den einfachen Anführungszeichen funktionieren:
PS1='${RED}\h $(get_path) ${exitStatus}${NONE} '
Dann haben Sie jedoch ein zweites Problem.
Versuchen Sie, dies auszuführen, und drücken Sie Up Arrowdann Home, und Ihr Cursor springt nicht zum Zeilenanfang zurück.
Um dies zu beheben, ändern Sie die Farb-Escape-Sequenzen PS1
in \[
und \]
um sie herum, z
PS1='\[${RED}\]\h $(get_path) $?\[${NONE}\] '
Sie können hier nicht get_exit_status
richtig verwenden, da die Ausgabe sowohl druckende (den Exit-Code) als auch nicht druckbare Zeichen (die Farbcodes) enthält und es keine Möglichkeit gibt, sie in der Eingabeaufforderung korrekt zu markieren. Durch das Setzen wird \[...\]
es als nicht vollständig gedruckt markiert, was nicht korrekt ist. Sie müssen die Funktion so ändern, dass nur der richtige Farbcode gedruckt wird, und ihn dann \[...\]
in der Eingabeaufforderung umgeben.
\[
ist\1
und\[
ist\2
. Diese entsprechen einer Readline-RL_PROMPT_{START,END}_IGNORE
Sache, die sie auffordert, die Bytes beim Zählen der Eingabeaufforderungslänge auf dem Bildschirm zu ignorieren. Siehe lists.gnu.org/archive/html/bug-bash/2015-08/msg00027.html .\]
ist\2
? Und meinst du, deshalb wird es gebraucht${exitStatus}
? Mein Punkt war, dass${exitStatus}
es keine nicht druckbaren Zeichen enthält, daher sollte bash in der Lage sein, korrekt zu bestimmen, wie viele Zeichen die Eingabeaufforderung ohne das\[
und\]
in verschoben wird\[${exitStatus}\]
.\e
und\033
(und\[
/\]
,\u
und\h
) an der Eingabeaufforderung, nur bevor die Variablen erweitert werden. SoPS1='\e[1;31m red'
funktioniert,red='\e[1;31m'; PS1='$red red'
tut es nicht.Wenn Sie ausführen
PS1='${RED}\h $(get_path) ${exitStatus}${NONE} '
, wird diePS1
Variable auf gesetzt${RED}\h $(get_path) ${exitStatus}${NONE}
, wobei nur\h
eine sofortige Escape-Sequenz angezeigt wird. Nachdem die Eingabeaufforderungssequenzen erweitert wurden (ergeben${RED}darkstar $(get_path) ${exitStatus}${NONE}
), führt die Shell die üblichen Erweiterungen durch, z. B. variable Erweiterungen. Sie erhalten eine angezeigte Eingabeaufforderung, die aussieht\e[1;31mdarkstar PATH 0\e[m
. Nichts auf dem Weg erweitert die\e
Sequenzen zu tatsächlichen Escape-Zeichen.Wenn Sie ausführen
PS1="${RED}\h $(get_path) ${exitStatus}${NONE} "
, wird diePS1
Variable auf gesetzt\e[1;31m\h PATH 0\e[m
. Die VariablenRED
,exitStatus
undNONE
werden zum Zeitpunkt der Zuordnung erweitert. Dann wird die Eingabeaufforderung enthält drei Aufforderung Escape - Sequenzen (\e
,\h
, und\e
wieder). Zu diesem Zeitpunkt müssen keine Shell-Variablen erweitert werden.Um Farben zu sehen, benötigen Sie die Farbvariablen, um tatsächliche Escape-Zeichen zu enthalten. Sie können es so machen:
$'…'
Erweitert Backslash-Octal-Sequenzen und einige Backslash-Letter-Sequenzen wie\n
, aber nicht einschließlich\e
. Ich habe drei weitere Änderungen an Ihrer Eingabeaufforderung vorgenommen:\[…\]
Option für nicht druckbare Sequenzen, z. B. Befehle zum Ändern der Farbe. Andernfalls wird Ihre Anzeige verstümmelt, da bash die Breite der Eingabeaufforderung nicht ermitteln kann.\w
ist eine integrierte Escape-Sequenz zum Drucken des aktuellen Verzeichnisses.$?
in der Eingabeaufforderung anzeigen, wenn Sie überhaupt keine habenPROMPT_COMMAND
.quelle
PS1
ist falsch, aber der Ratschlag$'...'
fürRED
undGREEN
sollte es mit Dogbane's funktionieren lassenPS1
.Versuchen:
quelle
Hier ist der Ansatz, den ich gewählt habe, er vermeidet die Verwendung von
PROMPT_COMMAND
.Dann ist mein
$PS1
wie folgt:quelle
$?
eine Ganzzahl sein kann, sollten Sieprintf '%b' "$GREEN"
stattdessen wirklich verwenden . Vermeiden Sie außerdem die Verwendung von Funktionsnamen, denen ein Präfix vorangestellt ist__
oder_
die bei der Bash-Vervollständigung verwendet werden.Los geht's - Das funktioniert für mich (TM) in Ubuntu und anderen Linuxen (Linuxen?).
Der Grund für das Einfügen der Exit-Code-Erkennung
$PS1
besteht darin, dass für einen Host ein schreibgeschützter$PROMPT_COMMAND
Satz festgelegt ist, bevor .bashrc gelesen wird.quelle
Denn
PROMPT_COMMAND
es ist sauberer, eine Funktion zu definieren und diese zu verwenden:quelle