¿Usa variables para almacenar códigos de color de terminal para PS1?


33

En mi .bashrc, uso códigos de color de terminal ANSI para colorear varios bits. Se parece a esto:

PS1='\u@\h:\w\[\033[33m\]$(virtual_env)\[\033[32m\]$(git_branch)\[\033[0m\]$ '

donde virtual_envy git_branchson funciones bash que generan cosas en stdout.

Ahora, para que sea más fácil de leer y modificar, me gustaría almacenar los códigos de color en variables y referirme a ellos, en lugar de incrustarlos directamente PS1. Entonces tengo un montón de variables como esta:

GREEN="\[\033[32m\]"
YELLOW="\[\033[33m\]"
RESET="\[\033[0m\]"

Me gustaría poder escribir algo como:

PS1='\u@\h:\w${YELLOW}$(virtual_env)${GREEN}$(git_branch)${RESET}$ '

Pero esto no funciona: los códigos de color aparecen en el mensaje, como si hubieran escapado. Los colores funcionan correctamente si uso comillas dobles en su lugar PS1, pero luego el aviso solo cambia cuando lo hago source ~/.bashrc.

He intentado otras cosas que he visto hacer a la gente: usar printf, usar comillas simples para los colores, poner el \[y \]en PS1lugar de la variable de color, pero nada parece funcionar.

¿Cómo puedo usar variables para los códigos de color?


¿Puedes darnos tu .bashrc?
Cuonglm

@cuonglm ¿Todos sus .bashrc nos pertenecen? Me mostraré afuera.
CivFan

Respuestas:


20

La solución es hacer que el shell sustituya las variables de color al definir el indicador, pero no las funciones. Para hacer esto, use las comillas dobles como había intentado originalmente, pero escape de los comandos para que no se evalúen hasta que se dibuje el mensaje.

PS1="\u@\h:\w${YELLOW}\$(virtual_env)${GREEN}\$(git_branch)${RESET}$ "

Observe el \antes de $()en cada comando.

Si hacemos eco de esto, vemos:

echo "$PS1"
\u@\h:\w\[\033[33m\]$(virtual_env)\[\033[32m\]$(git_branch)\[\033[0m\]$ 

Como puede ver, las variables de color se sustituyeron, pero no los comandos.


1
Esto no parece funcionar si $ (git_branch) también está intentando imprimir usando $ {YELLOW}, etc. Solo en esa sección, obtendrá todos los caracteres [].
WB Reed

7

El problema es que tu variable GREEN contiene la cadena literal que consiste en "barra diagonal inversa barra invertida cero tres tres" y así sucesivamente. No contiene, por ejemplo, un carácter de escape ASCII como se requiere para que su terminal cambie de color.

Se puede poner en caracteres de control GREEN(y YELLOW, y RESET) de forma manual, pero una opción mucho mejor es utilizar tputen primer lugar, por lo que no es necesario codificar nada y va a apoyar cualquier tipo de terminal.

GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
RESET="$(tput setaf 0)"

La razón por la cual el mundo cuando pones "barra invertida cero tres tres", etc ... directamente PS1es que la interpretación de ciertas secuencias de barra invertida es una característica de la incitación de bash (vea la sección PROPUESTA en el manual. Esta sustitución ocurre antes de la expansión de parámetros, comando sin embargo, la sustitución aritmética y la eliminación de comillas no se aplican a los resultados de todas esas otras operaciones.


55
Al hacerlo de esta manera, debe ajustar las variables de color \[\]dentro del $PS1. Por ejemplo: PS1='\u@\h:\w\[${YELLOW}\]'. Si no haces esto y terminas con un comando largo que pasa a la siguiente línea, encontrarás todo tipo de problemas. El shell utiliza \[\]para determinar qué caracteres no se pueden imprimir, por lo que no los tiene en cuenta en el cálculo de la longitud de la solicitud. Necesita esto para poder dibujar la línea correctamente cuando excede el ancho del terminal.
Patrick

No lo sabía tput, gracias. Usaré la respuesta de Patrick por ahora, pero volveré a ver esto cuando tenga la oportunidad.
Ismail Badawi

2

Cambie la forma en que llena $ GREEN, $ YELLOW y $ RESET:

GREEN="$(echo -e "\033[32m")"
YELLOW="$(echo -e "\033[33m")"
RESET="$(echo -e "\033[0m")"

PS1='\u@\h:\w${YELLOW}$(virtual_env)${GREEN}$(git_branch)${RESET}$ '

1
En efecto, esto hace exactamente lo mismo que la respuesta de Celada. Pero Celada es más portátil en caso de que el terminal use diferentes códigos de escape para la configuración del color. También va a tener el mismo problema con el mensaje de varias líneas.
Patrick

2
El \[…\]bit debe permanecer en el indicador, no puede rellenarlo en una variable. Lo ha eliminado por completo, lo que provocará problemas de visualización (el cursor no está en la posición donde bash lo espera).
Gilles 'SO- deja de ser malvado'

Aparte de las preocupaciones de @Patrick, echo -e no es portátil.
helpermethod el

1
Con la no portabilidad, vienen más funciones: tput setafno le permite elegir entre el conjunto de colores "claros", como el cian claro. La respuesta de @ Cyrus, sin embargo, sí.
CivFan
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.