
Um die gleiche Ausgabe zu erhalten, die Sie in Ihrer Frage notiert haben, ist nur Folgendes erforderlich:
PS1='${PS2c##*[$((PS2c=0))-9]}- > '
PS2='$((PS2c=PS2c+1)) > '
Sie brauchen sich nicht zu verziehen. Diese beiden Zeilen funktionieren in jeder Shell, die eine POSIX-Kompatibilität vorgibt.
- > cat <<HD
1 > line 1
2 > line $((PS2c-1))
3 > HD
line 1
line 2
- > echo $PS2c
0
Aber mir hat das gefallen. Und ich wollte die Grundlagen dafür demonstrieren, was diese Arbeit ein bisschen besser macht. Also habe ich das ein wenig bearbeitet. Ich habe es /tmperstmal reingesteckt, aber ich denke, ich werde es auch für mich behalten. Es ist hier:
cat /tmp/prompt
PROMPT SCRIPT:
ps1() { IFS=/
set -- ${PWD%"${last=${PWD##/*/}}"}
printf "${1+%c/}" "$@"
printf "$last > "
}
PS1='$(ps1)${PS2c##*[$((PS2c=0))-9]}'
PS2='$((PS2c=PS2c+1)) > '
Hinweis: Nachdem ich kürzlich von Yash erfahren habe , habe ich es gestern gebaut. Aus irgendeinem Grund gibt es nicht das erste Byte jedes Arguments mit der %cZeichenfolge aus - obwohl die Dokumente spezifisch für Wide-Char-Erweiterungen für dieses Format waren und es möglicherweise damit zusammenhängt -, aber es ist in Ordnung mit%.1s
Das ist die ganze Sache. Dort oben gehen zwei Dinge vor. Und so sieht es aus:
/u/s/m/man3 > cat <<HERE
1 > line 1
2 > line 2
3 > line $((PS2c-1))
4 > HERE
line 1
line 2
line 3
/u/s/m/man3 >
PARSING $PWD
Jedes Mal, wenn $PS1es ausgewertet wird, wird es analysiert und gedruckt $PWD, um es der Eingabeaufforderung hinzuzufügen. Aber ich mag es nicht, wenn $PWDmein Bildschirm voll ist, deshalb möchte ich nur den ersten Buchstaben jedes Breadcrumbs im aktuellen Pfad bis zum aktuellen Verzeichnis, das ich gerne vollständig sehen würde. So was:
/h/mikeserv > cd /etc
/etc > cd /usr/share/man/man3
/u/s/m/man3 > cd /
/ > cd ~
/h/mikeserv >
Hier gibt es ein paar Schritte:
IFS=/
Wir müssen den Strom aufteilen, $PWDund der zuverlässigste Weg, dies zu tun, ist $IFSSplit on /. Danach brauchen Sie sich überhaupt nicht mehr darum zu kümmern - alle Aufteilungen von hier an werden durch das Positionsparameter- $@Array der Shell im nächsten Befehl wie folgt definiert :
set -- ${PWD%"${last=${PWD##/*/}}"}
Das ist ein bisschen knifflig, aber die Hauptsache ist, dass wir uns $PWDauf /Symbole aufteilen. Ich verwende auch die Parametererweiterung, um $lastnach jedem Wert, der zwischen dem /Schrägstrich ganz links und ganz rechts liegt , alles zuzuweisen . Auf diese Weise weiß ich, dass wenn ich gerade dabei bin /und nur einen habe, /dann $lastimmer noch das Ganze gleich ist $PWDund $1leer sein wird. Das ist wichtig. Ich entferne auch $lastdas hintere Ende von, $PWDbevor ich es zuordne $@.
printf "${1+%c/}" "$@"
Also hier - solange ${1+is set}wir printfdas erste %cZeichen der Argumente unserer Shell sind - das wir gerade auf jedes Verzeichnis in unserem aktuellen $PWD- abzüglich des obersten Verzeichnisses - aufgeteilt haben /. Wir drucken also im Wesentlichen nur das erste Zeichen jedes Verzeichnisses $PWDaußer dem obersten. Es ist jedoch wichtig zu wissen, dass dies nur dann geschieht, wenn $1es überhaupt gesetzt wird, was nicht bei root /oder bei einem, der von /solchen wie in entfernt wird, der Fall ist /etc.
printf "$last > "
$lastist die Variable, die ich gerade unserem Hauptverzeichnis zugewiesen habe. Das ist also unser oberstes Verzeichnis. Es wird gedruckt, ob die letzte Anweisung dies tat oder nicht. Und es braucht ein ordentliches kleines >Maß.
ABER WAS IST MIT DER ERHÖHUNG?
Und dann ist da noch die Sache mit der $PS2Bedingung. Ich habe bereits früher gezeigt, wie dies gemacht werden kann. Dies ist grundsätzlich eine Frage des Umfangs. Aber es printf \bsteckt noch ein bisschen mehr dahinter, es sei denn, Sie möchten eine Reihe von Ackspaces erstellen und dann versuchen, die Anzahl ihrer Charaktere auszugleichen ... ugh. Also mache ich das:
PS1='$(ps1)${PS2c##*[$((PS2c=0))-9]}'
Auch hier ${parameter##expansion}spart der Tag. Hier ist es allerdings etwas seltsam - wir setzen die Variable tatsächlich, während wir sie selbst entfernen. Wir verwenden seinen neuen Wert - Set Mid-Strip - als Glob, von dem wir entfernen. Siehst du? Wir ##*streifen alles vom Kopf unserer Inkrementvariablen bis zum letzten Zeichen ab, von dem alles sein kann [$((PS2c=0))-9]. Auf diese Weise wird garantiert, dass der Wert nicht ausgegeben wird, und wir weisen ihn dennoch zu. Es ist ziemlich cool - das habe ich noch nie gemacht. POSIX garantiert uns aber auch, dass dies die portabelste Art ist, dies zu tun.
Dank POSIX ${parameter} $((expansion))bleiben diese Definitionen in der aktuellen Shell, ohne dass wir sie in einer separaten Subshell festlegen müssen, unabhängig davon, wo wir sie auswerten. Und deshalb funktioniert es in dashund shgenauso gut wie in bashund zsh. Wir verwenden keine Shell / Terminal-abhängigen Escapes und lassen die Variablen selbst testen. Das macht portablen Code schnell.
Der Rest ist ziemlich einfach - erhöhen Sie einfach unseren Zähler für jedes Mal $PS2, wenn $PS1er ausgewertet wird, bis er wieder zurückgesetzt wird. So was:
PS2='$((PS2c=PS2c+1)) > '
So jetzt kann ich:
DASH DEMO
ENV=/tmp/prompt dash -i
/h/mikeserv > cd /etc
/etc > cd /usr/share/man/man3
/u/s/m/man3 > cat <<HERE
1 > line 1
2 > line 2
3 > line $((PS2c-1))
4 > HERE
line 1
line 2
line 3
/u/s/m/man3 > printf '\t%s\n' "$PS1" "$PS2" "$PS2c"
$(ps1)${PS2c##*[$((PS2c=0))-9]}
$((PS2c=PS2c+1)) >
0
/u/s/m/man3 > cd ~
/h/mikeserv >
SH DEMO
Es funktioniert genauso in bashoder sh:
ENV=/tmp/prompt sh -i
/h/mikeserv > cat <<HEREDOC
1 > $( echo $PS2c )
2 > $( echo $PS1 )
3 > $( echo $PS2 )
4 > HEREDOC
4
$(ps1)${PS2c##*[$((PS2c=0))-9]}
$((PS2c=PS2c+1)) >
/h/mikeserv > echo $PS2c ; cd /
0
/ > cd /usr/share
/u/share > cd ~
/h/mikeserv > exit
Wie oben erwähnt, besteht das Hauptproblem darin, dass Sie sich überlegen müssen, wo Sie Ihre Berechnung durchführen. Sie erhalten den Status nicht in der übergeordneten Shell - also berechnen Sie dort nicht. Sie erhalten den Status in der Subshell - also rechnen Sie dort. Aber Sie machen die Definition in der übergeordneten Shell.
ENV=/dev/fd/3 sh -i 3<<\PROMPT
ps1() { printf '$((PS2c=0)) > ' ; }
ps2() { printf '$((PS2c=PS2c+1)) > ' ; }
PS1=$(ps1)
PS2=$(ps2)
PROMPT
0 > cat <<MULTI_LINE
1 > $(echo this will be line 1)
2 > $(echo and this line 2)
3 > $(echo here is line 3)
4 > MULTI_LINE
this will be line 1
and this line 2
here is line 3
0 >
man 1 mktemp.