Para obtener el mismo resultado que anota en su pregunta, todo lo que se necesita es esto:
PS1='${PS2c##*[$((PS2c=0))-9]}- > '
PS2='$((PS2c=PS2c+1)) > '
No necesitas contorsionar. Esas dos líneas lo harán todo en cualquier shell que simule algo cercano a la compatibilidad POSIX.
- > cat <<HD
1 > line 1
2 > line $((PS2c-1))
3 > HD
line 1
line 2
- > echo $PS2c
0
Pero me ha gustado esto. Y quería demostrar los fundamentos de lo que hace que esto funcione un poco mejor. Así que edité esto un poco. Lo puse /tmp
por ahora, pero creo que también me lo guardaré. Esta aquí:
cat /tmp/prompt
GUIÓN INMEDIATA:
ps1() { IFS=/
set -- ${PWD%"${last=${PWD##/*/}}"}
printf "${1+%c/}" "$@"
printf "$last > "
}
PS1='$(ps1)${PS2c##*[$((PS2c=0))-9]}'
PS2='$((PS2c=PS2c+1)) > '
Nota: habiendo aprendido recientemente de yash , lo construí ayer. Por alguna razón, no imprime el primer byte de cada argumento con la %c
cadena, aunque los documentos eran específicos sobre las extensiones de ancho ancho para ese formato y, por lo tanto, pueden estar relacionados, pero funciona bien con%.1s
Eso es todo. Hay dos cosas principales que suceden allí arriba. Y así es como se ve:
/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
Cada vez que $PS1
se evalúa, se analiza e imprime $PWD
para agregar a la solicitud. Pero no me gusta que toda $PWD
mi pantalla se llene, así que solo quiero la primera letra de cada ruta de navegación en la ruta actual hasta el directorio actual, que me gustaría ver en su totalidad. Me gusta esto:
/h/mikeserv > cd /etc
/etc > cd /usr/share/man/man3
/u/s/m/man3 > cd /
/ > cd ~
/h/mikeserv >
Aquí hay algunos pasos:
IFS=/
Vamos a tener que dividir la corriente $PWD
y la forma más confiable de hacerlo es $IFS
dividir /
. No es necesario molestarse con eso después: toda la división de aquí en adelante se definirá por la $@
matriz de parámetros posicionales del shell en el siguiente comando como:
set -- ${PWD%"${last=${PWD##/*/}}"}
Esto es un poco complicado, pero lo principal es que nos estamos dividiendo $PWD
en /
símbolos. También utilizo la expansión de parámetros para asignar a $last
todo después de cualquier valor que ocurra entre la /
barra diagonal izquierda y la derecha . De esta manera sé que si estoy justo en /
y tienen un único /
entonces $last
todavía será igual a la totalidad $PWD
y $1
estará vacía. Esto importa También me quito $last
el extremo de la cola $PWD
antes de asignarlo $@
.
printf "${1+%c/}" "$@"
Entonces, aquí, siempre que ${1+is set}
seamos printf
el primer %c
personaje de cada uno de los argumentos de nuestro shell, que acabamos de establecer en cada directorio de nuestro actual $PWD
, menos el directorio superior, se divide /
. Esencialmente, solo estamos imprimiendo el primer carácter de cada directorio, $PWD
excepto el superior. Sin embargo, es importante darse cuenta de que esto solo sucede si $1
se establece, lo que no sucederá en la raíz /
o en uno eliminado /
, como en /etc
.
printf "$last > "
$last
es la variable que acabo de asignar a nuestro directorio superior. Así que ahora este es nuestro directorio principal. Imprime si la última declaración lo hizo o no. Y se necesita un poco limpio >
por si acaso.
¿Pero qué hay del incremento?
Y luego está el asunto de lo $PS2
condicional. Mostré anteriormente cómo se puede hacer esto, que aún puede encontrar a continuación: esto es fundamentalmente una cuestión de alcance. Pero hay un poco más a menos que desees comenzar a hacer un montón de printf \b
espacios y luego tratar de equilibrar su cuenta de personajes ... ugh. Entonces hago esto:
PS1='$(ps1)${PS2c##*[$((PS2c=0))-9]}'
De nuevo, ${parameter##expansion}
salva el día. Sin embargo, es un poco extraño aquí: en realidad establecemos la variable mientras la despojamos de sí misma. Usamos su nuevo valor, establecer mid-strip, como el glob del que nos despojamos. ¿Lo ves? Nos ##*
despojamos de todo de la cabeza de nuestra variable de la subasta hasta el último carácter que puede ser cualquier cosa de [$((PS2c=0))-9]
. De esta forma, tenemos la garantía de no generar el valor, y aún así lo asignamos. Es genial, nunca lo había hecho antes. Pero POSIX también nos garantiza que esta es la forma más portátil de hacerlo.
Y es gracias a POSIX-especificado ${parameter} $((expansion))
que mantiene estas definiciones en el shell actual sin requerir que las establezcamos en un subshell separado, independientemente de dónde las evaluamos. Y es por eso que funciona en dash
y sh
tan bien como en bash
y zsh
. No utilizamos escapes dependientes de shell / terminal y dejamos que las variables se prueben a sí mismas. Eso es lo que hace que el código portátil sea rápido.
El resto es bastante simple: solo incremente nuestro contador por cada vez que $PS2
se evalúe hasta que $PS1
una vez más se restablezca. Me gusta esto:
PS2='$((PS2c=PS2c+1)) > '
Entonces ahora puedo:
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
Funciona igual en bash
o 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
Como dije anteriormente, el problema principal es que debes considerar dónde haces tu cálculo. No obtiene el estado en el shell principal, por lo que no calcula allí. Obtiene el estado en la subshell, así que ahí es donde calcula. Pero haces la definición en el shell principal.
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
.