¿Cómo incluir comandos en la PS1 de Bash sin romper el cálculo de la longitud de línea?

13

Tonin señaló un error en mi mensaje predeterminado . Ejemplo mínimo:

  1. Establecer PS1:

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

    En este punto, el indicador se ve así:

    $ 
  2. Ahora active la salida del código de salida ejecutando:

    false

    Ahora el mensaje contiene el código de salida en rojo al comienzo de la línea:

    1 $ 
  3. Presione Ctrl- r.
  4. Escriba "falso". Ahora el mensaje contiene solo la búsqueda:

    (reverse-i-search)`false': false
  5. Presione Enter.

El historial del terminal resultante ahora contiene lo siguiente:

1 $ch)`false': false

Rendimiento esperado:

1 $ false

Es decir, parece que el resultado de la búsqueda del historial se mezcla con la solicitud y oculta el comando real que se ejecutó.

Intenté solucionar esto usandoPROMPT_COMMAND :

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

Esto no parece funcionar: la línea se ve exactamente igual que antes después de buscar y ejecutar.

¿Cómo puedo arreglar esto?

l0b0
fuente
1
Esta parece ser la continuación de unix.stackexchange.com/a/71012
manatwork

Respuestas:

8

Encontré la respuesta en askubuntu.com . @ qeirha mencionó que tiene que decirle a bash que la secuencia de caracteres no debe contarse en la longitud de la solicitud, y lo hace al encerrarla \[ \]. Según el ejemplo proporcionado, aquí hay una solución:

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
fuente
No hay necesidad de ir a preguntarle a Ubuntu . Ya tenemos suficientes respuestas a esta pregunta aquí también.
manatwork
Gracias por el consejo @manatwork! Quería dar el crédito adecuado por la explicación y proporcioné la referencia como cortesía.
Timothy Martin
Dar crédito no es un problema. Pero mientras hablamos del problema: las barras invertidas sin escape solían desaparecer de Markdown, por lo que su simple \ [se convirtió en [en su publicación, por lo tanto, el código mostrado no era funcional al copiarlo y pegarlo en la terminal. Esto se puede evitar utilizando código en línea o marcado de bloque de código. ( ¿Cómo formateo mis publicaciones usando Markdown o HTML? )
manatwork
1
D'oh! Ya solucioné el mismo problema para otro PS1código, ¿por qué no vi ese?
l0b0
1
PS1='$(exit_code=$?; [[ $exit_code -eq 0 ]] || printf %s \[$(tput setaf 1)\] $exit_code \[$(tput sgr0)\] " ")$ '

(Lo sentimos, no hay explicación aquí. Consulte ¿Cómo personalizar la PS1 correctamente? O cualquier otra pregunta sobre problemas de cálculo de la longitud del indicador y \[... \])

manatwork
fuente
A la segunda pregunta @ l0b0, agregaré eso usando PS1 y \[...\]funciona bien siempre que pueda poner todo el código que desea generar su solicitud en una sola cadena. Sin embargo, si desea dividir su código en pequeñas funciones, llega a un punto en el que no puede colocar los corchetes iniciales y finales en la misma cadena / función. Y eso rompe la línea de envoltura. A menos que recurra al uso PROMPT_COMMANDpara volver a calcular su PS1en cada solicitud.
Tonin
1

Ampliando la respuesta @manatwork pero manteniendo su código dividiendo el PS1cálculo en diferentes funciones, puede escribir su mensaje de la siguiente manera:

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

Las comillas dobles son obligatorias tanto cuando se configura PS1como cuando se usa printfen la función.

Tonin
fuente
Para referencia futura, use una función bash en su .bashrc- no ponga el código en un archivo separado y llame a eso.
starbeamrainbowlabs