Wie füge ich Befehle in Bashs PS1 ein, ohne die Berechnung der Zeilenlänge zu unterbrechen?

13

Tonin wies auf einen Fehler in meiner Standardaufforderung hin . Minimales Beispiel:

  1. PS1 einstellen:

    PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s $(tput setaf 1) $exit_code $(tput sgr0) " ")$ '

    Zu diesem Zeitpunkt sieht die Eingabeaufforderung folgendermaßen aus:

    $ 
  2. Lösen Sie nun die Ausgabe des Exit-Codes aus, indem Sie Folgendes ausführen:

    false

    Jetzt enthält die Eingabeaufforderung den Beendigungscode in rot am Anfang der Zeile:

    1 $ 
  3. Drücken Sie Ctrl- r.
  4. Geben Sie "false" ein. Jetzt enthält die Eingabeaufforderung nur die Suche:

    (reverse-i-search)`false': false
  5. Drücken Sie Enter.

Die resultierende Terminal-Historie enthält nun Folgendes:

1 $ch)`false': false

Erwartete Ausgabe:

1 $ false

Das heißt, die Ausgabe der Verlaufssuche scheint mit der Eingabeaufforderung gemischt zu sein und den tatsächlich ausgeführten Befehl auszublenden.

Ich habe versucht, dies zu umgehen, indemPROMPT_COMMAND ich Folgendes verwendete :

set_exit_code() {
    exit_code=$?
    [[ $exit_code -eq 0 ]] || printf %s $(tput setaf 1) $exit_code $(tput sgr0) " "
}
set_bash_prompt() {
    PS1='$(set_exit_code)$ ' # Double quotes give the same result
}
PROMPT_COMMAND=set_bash_prompt

Dies scheint nicht zu funktionieren - die Linie sieht nach dem Suchen und Ausführen genauso aus wie zuvor.

Wie kann ich das beheben?

l0b0
quelle
1
Dies scheint die Fortsetzung von unix.stackexchange.com/a/71012
manatwork

Antworten:

8

Ich habe die Antwort auf askubuntu.com gefunden . @qeirha erwähnte, dass Sie bash mitteilen müssen, dass die Zeichenfolge nicht in der Länge der Eingabeaufforderung gezählt werden soll, und Sie tun dies, indem Sie sie einschließen \[ \]. Anhand des angegebenen Beispiels ist hier eine Lösung:

red=$(tput setaf 1)

reset=$(tput sgr0)

[ "$PS1" = "\\s-\\v\\\$ " ] && PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s \[$red\] $exit_code \[$reset\] " ")$ '
Timothy Martin
quelle
Es ist nicht nötig, Ubuntu danach zu fragen . Auch hier haben wir bereits genügend Antworten auf diese Frage.
manatwork
Vielen Dank für den Rat @manatwork! Ich wollte die Erklärung angemessen würdigen und stellte die Referenz mit freundlicher Genehmigung zur Verfügung.
Timothy Martin
Kredit zu geben ist kein Problem. Aber während wir über das Problem sprechen: unausgekappte Backslashes verschwanden von Markdown, so dass Ihr einfacher Code in Ihrem Beitrag nicht mehr funktionierte, indem er in das Terminal kopiert wurde. Dies kann durch die Verwendung von Inline-Code oder Code-Block-Markup vermieden werden. ( Wie formatiere ich meine Posts mit Markdown oder HTML? )
manatwork
1
D'oh! Ich habe das gleiche Problem bereits für anderen PS1Code behoben. Warum habe ich diesen nicht gesehen?
l0b0
1
PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s \[$(tput setaf 1)\] $exit_code \[$(tput sgr0)\] " ")$ '

(Sorry, keine Erklärung hier. Siehe PS1 richtig anpassen? Oder eine andere Frage zu Problemen bei der Berechnung der Prompt-Länge und \[... \])

Handarbeit
quelle
Zur zweiten @ l0b0-Frage füge ich das mit PS1 hinzu und es \[...\]funktioniert, solange Sie den gesamten Code, den Sie für Ihre Eingabeaufforderung generieren möchten, in eine einzige Zeichenfolge schreiben können. Wenn Sie Ihren Code jedoch in kleine Funktionen aufteilen möchten, können Sie die Anfangs- und Endeklammer nicht mehr in dieselbe Zeichenfolge / Funktion setzen. Und das bricht Zeilenumbruch. Es sei denn, Sie verwenden PROMPT_COMMAND, um Ihre PS1bei jeder Eingabeaufforderung neu zu berechnen .
Tonin
1

Wenn Sie @manatwork answer erweitern, den Code jedoch PS1in verschiedene Funktionen aufteilen , können Sie die Eingabeaufforderung folgendermaßen schreiben:

set_exit_code() {
    exit_code=$?
    [[ $exit_code -eq 0 ]] || printf "\[$(tput setaf 1)\] $exit_code \[$(tput sgr0)\] "
}
set_bash_prompt() {
    PS1="$(set_exit_code)$ " # with double quotes!
}
PROMPT_COMMAND=set_bash_prompt

Doppelte Anführungszeichen sind sowohl bei der Einstellung PS1als auch bei der Verwendung printfin der Funktion obligatorisch .

Tonin
quelle
Verwenden Sie zum späteren Nachschlagen eine Bash-Funktion in Ihrer .bashrc- schreiben Sie den Code nicht in eine separate Datei und rufen Sie diese auf.
Starbeamrainbowlabs