2012-08-09 6 views
12

Dies könnte ein bisschen Rand sein, aber ich zog vor kurzem nach Zsh und habe ein Problem bei der Anpassung meiner Shell-Eingabeaufforderung.zsh re-computing meine Shell-Eingabeaufforderung

Teil meiner .zshrc sieht wie folgt aus:

# keeping this simple right now by just printing the date, but imagine this function would look for something specific when moving to a new directory each time 
function parse_special { 
    print $(date) 
} 

autoload -U colors && colors 
PS1="%{$fg[green]%}%[email protected]%m %{$fg[blue]%}%c %{$fg[yellow]%}%{$(parse_special)%} %{$reset_color%}%# " 

Wenn ich Terminal starten, alles sieht gut aus; meine Aufforderung ist das, was ich erwarte:

[email protected] ~ Wed Aug 8 22:56:22 PDT 2012 % 

Aber wenn ich cd in ein anderes Verzeichnis, es ist meine parse_special Funktion erscheint nicht aufgerufen, wieder meine benutzerdefinierte Prompt (man beachte das Datum ändert sich nicht) neu zu berechnen:

[email protected] ~ Wed Aug 8 22:56:22 PDT 2012 % cd .ssh 
[email protected] .ssh Wed Aug 8 22:56:22 PDT 2012 % cd ../workspace 
[email protected] workspace Wed Aug 8 22:56:22 PDT 2012 % 

Gibt es eine Möglichkeit, zSH die Eingabeaufforderung jedes Mal erneut zu berechnen, wenn es angezeigt wird?

vielen Dank für Anregungen.


Antwort

Es ist wie PS1 von einzelnen angegebenen Werte gesetzt bekommen nicht scheint cjhveal gerne. Ich habe versucht, die folgenden:

local tp1="%{$fg[green]%}%[email protected]%m%{$reset_color%}" 
PS1="${tp1}" 
print "PS1 set by tp1: ${PS1}" 
local tp2='%{$fg[green]%}%[email protected]%m%{$reset_color%}' 
PS1="${tp2}" 
print "PS1 set by tp2: ${PS1}" 

Und bekam diese Ausgabe

#inner stuff was green 
PS1 set by tp1: %{%}%[email protected]%m%{%} 
#everything was uncolored 
PS1 set by tp2: %{$fg[green]%}%[email protected]%m%{$reset_color%} 

Ich möchte auch hinzufügen, basierend auf cjhveal Vorschlag, hier ist das, was ich buchstäblich versucht. Auch hier scheinen die einfachen Anführungszeichen Dinge

function parse_special {  
    print $(date) 
} 

autoload -U colors && colors 
local prompt_user='%{$fg[green]%}%[email protected]%m%{$reset_color%}' 
local prompt_root='%{$fg[red]%}%[email protected]%m%{$reset_color%}' 
local prompt_dir='%{$fg[blue]%}%c%{$reset_color%}' 
local prompt_special='%{$fg[yellow]%}%{$(parse_special)%}%{$reset_color%}' 
PS1="${prompt_user} ${prompt_dir}${prompt_special}%# " 

Antwort

14

Ich lief in das gleiche Problem zu verwirren, während in zsh meine prompte Anpassung.

Ich glaube, das passiert, weil die Shell den Wert in die Zeichenfolge einmal interpoliert, wenn die Eingabeaufforderung initialisiert wird. Nachfolgende Neuladungen haben in Ihrer Eingabeaufforderung die Konstante string, nicht die Subshell-Interpolation.

Setzen Sie stattdessen alle Zeilen, die Subshells enthalten, in eine Variable, die mit einfachen Anführungszeichen definiert ist. Dann interpoliere stattdessen diese Variable.

autoload -U colors && colors 

local parse_special='%{$fg[yellow]%}$(date)%{$reset_color%}' 

PS1="%{$fg[green]%}%[email protected]%m %{$fg[blue]%}%c ${parse_special} %# " 

Update: Hinzufügen von dieser von ZyX-Antwort, um eine vollständige Lösung für diese zu machen. Sie müssen auch diese hinzufügen:

setopt promptsubst 

In der Tat, würde ich vorschlagen, jeden Teil Ihres prompt in eine Variable wie folgt zu extrahieren, darunter ein reset_color auf jedem. Auf diese Weise können Sie die Reihenfolge der Eingabeaufforderungskomponenten ändern, ohne die Implementierung zu ändern.

+0

danke für die Antwort. Ich denke, das ist die richtige Lösung, aber ich muss immer noch etwas falsch machen (siehe die Bearbeitung, die ich zu meinem ursprünglichen Beitrag gemacht habe). Scheint so, als könnte ich hier keine einfachen Anführungszeichen verwenden. Können Sie auch erklären, warum die Verwendung von einfachen Anführungszeichen in Ihrer Antwort wichtig ist? Wird var = "$ (do_stuff)" anders behandelt als var = '$ (do_stuff)'? –

+0

Versuchen Sie, die um die Subshell gewickelte% {%} zu entfernen. Ich weiß nicht warum, aber es funktioniert für mich ohne sie. Der Unterschied zwischen einfachen und doppelten Anführungszeichen besteht darin, wie die Shell die Interpolation durchführt. var = "$ (do_stuff)" führt die Subshell sofort aus und interpoliert das Ergebnis einmalig. Wenn Sie einfache Anführungszeichen verwenden, wird diese Subshell nicht interpretiert und bleibt als Literalkonstante erhalten, bis sie in eine Zeichenfolge mit doppelten Anführungszeichen interpoliert wird. Dann wird es ausgeführt. Im Wesentlichen wird gewartet, bis die Aufforderung zur Ausführung der Subshells aktualisiert wird. – cjhveal

+1

@cjhveal '% {' '%}' schließen Sie den Text ein, den zsh als Null-Breite betrachten sollte (normalerweise Sequenzen, die Terminal anweisen, etwas mit dem folgenden Text zu tun, wie die Farbe zu ändern). Wenn Sie Text mit nicht-Null-Breite darin einschließen, wird es immer noch angezeigt, aber mit einer Reihe von Fehlern (zum Beispiel sagt zsh dem Terminal, dass er den Cursor auf eine bestimmte Position setzen möchte und Text dort ablegt.) Nicht-Null-Breite-Text%} 'wird diese Position falsch machen und Sie erhalten Text, der Prompt überschreibt und in Promptfarbe eingefärbt ist. – ZyX

7

Sie sind Hälfte der Weg zur Lösung dieses Problems:

PS1='$(date)' 

werden Sie prompt $(date) zeigen, aber

PS1='$(date)' 
setopt promptsubst 

zeigt Ihnen prompt Thu Aug 9 21:01:53 MSK 2012 (abhängig von $LANG und $LC_TIME, natürlich) .

By the way, in der neuesten zsh Sie nicht brauchen %{$fg[blue]%} mehr zu verwenden, nos %F{blue} für Vordergrund ist, %K{blue} für den Hintergrund, %f%k für sie und ein paar andere Zurücksetzen des Gerätes finden man zshmisc, Abschnitt EXPANSION OF PROMPT SEQUENCES.

+0

ah, yeah Einstellung setopt promsubst war das Stück, das ich vermisste. Danke vielmals. Ich werde die obige Antwort bearbeiten, um diese Zeile hinzuzufügen, um aus diesen beiden eine vollständige Antwort zu machen. Danke noch einmal. –