2012-05-12 9 views
13

Ich würde gerne meine aktuelle git Zweig in meine Multi-Linie ZSH Prompt setzen. Dies verwirrt jedoch die beiden Zeilen - ich möchte, dass sie sich gut aneinanderreihen.Zählen Länge der Benutzer sichtbare Zeichenfolge für Zsh-Eingabeaufforderung


┌─([email protected]:s000)─[master *]──────────────── 
───(~ )─┐ 
└─(127:15:44)──      ──(Sat,May12)─┘ 

sollte sein:


┌─([email protected]:s000)─[master *]─────────(~ )─┐ 
└─(127:15:44)──      ──(Sat,May12)─┘ 

Der git Zweig wird aus einer oh-my-zsh Funktion packt, git_prompt_info(), die mir den Ast, schmutzigen Zustand, und eine Reihe von Prompt-entkommt gibt schön Dinge zu färben.

Wie zähle ich die Zeichen, die sichtbar sind eingefügt in die ZSH-Eingabeaufforderung - nicht die Aufforderung Escape-Sequenzen?

Antwort

11

Unter der Annahme, dass die Abfrage-Escape-Sequenzen in einer Variablen FOO gespeichert sind, wird dies nur für Benutzer sichtbare Zeichen zählen:

                                
FOO=$(git_prompt_info)                              
local zero='%([BSUbfksu]|([FK]|){*})' 
FOOLENGTH=${#${(S%%)FOO//$~zero/}} 

Das kommt von this .zshrc.

Dies ist eine grobe Erklärung, warum es funktioniert, frei aus man zshexpn zitiert, Abschnitt PARAMETER EXPANSION. Ich bin mir der Details nicht 100% ig sicher. Wenn Sie damit Ihr eigenes Äquivalent entwickeln, lesen Sie die entsprechenden Abschnitte man zshall.

Arbeiten von der Linie FOOLENGTH=${#${(S%%)FOO//$~zero/}}, wir haben eine Reihe von Bits. Wenn man von innen nach außen:

  1. $~zero: Die ~ sorgt dafür, dass zero, die wir als '%([BSUbfksu]|([FB]|){*})' definiert haben, als ein Muster behandelt wird und nicht als einfacher String.

  2. ${(S%%)FOO//$~zero/}: Das passt ${name//pattern/repl}:

    Ersetzen Sie die längste mögliche Übereinstimmung der Muster in den Ausbau der Parameternamen von String repl

    Beachten Sie, dass wir nicht über eine repl; Wir ersetzen das längste mögliche Spiel von pattern durch nichts und entfernen es dadurch.
    (S%%)FOO führt eine Erweiterung auf FOO mit mehreren Flags festgelegt. Ich folge es nicht ganz.

  3. ${#${(S%%)FOO//$~zero/}}: ${#spec} wird die Länge in Zeichen des Ergebnisses der Substitution spec, substitue spec wenn eine Substitution ist. In unserem Fall ist spec das Ergebnis der Substitution ${(S%%)FOO//$~zero/}; also gibt dies im Grunde die Länge der Zeichen im Ergebnis des regulären Ausdrucks auf FOO zurück, wobei zero das obige Muster ist.

+4

'(S)' macht passende nicht-gierige so „längste mögliche Übereinstimmung“ in den „kürzeste mögliche Übereinstimmung“ drehen (ohne es '{*}' in einem Muster wird Sache drehen wie '% F {blau}% M% F {gelb}% #% f' in nur'% #', während es in '% M% #' umgewandelt werden soll, '' (%%) 'führt eine prompte Expansion auf dem Zeichenfolge, folgende PROMPT_ * -Optionen. Hinweis: Diese Methode sollte vermieden werden, wenn die PROMPT-Zeichenfolge einen Befehl mit einigen Nebenwirkungen enthält: Wenn Sie z. B. verwenden möchten, um zu zählen, wie oft die Eingabeaufforderung angezeigt wird. Die meiste Zeit wirst du nicht darunter leiden. – ZyX

+0

Und ja, alle '(*) 'Flags werden im Abschnitt PARAMETER EXPANSION von' man zshexpn' beschrieben. – ZyX

+0

@ ZyX Danke. Ich sah die Erklärung für 'S' auf der Seite' zshexpn', war mir aber nicht sicher, wie es dazu passte. – simont

2

nicht sicher, wie dies zu tun mit builtin zsh Befehlen, aber Farbinformationen können mit sed abgezogen werden (wie here dokumentiert):

sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g" 

z.B.

plain_str=$(git_prompt_info | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g") 

Das würde alle Escape-Sequenzen aus der Zeichenfolge entfernen. Die Länge ist jetzt einfach:

echo $#plain_str 
+0

@beardtree: Danke für die vorgeschlagene Bearbeitung. – Thor

Verwandte Themen