¿Cómo soluciono el ajuste del mensaje de bash de color?

¿Cómo soluciono el ajuste del mensaje de bash de color?

He definido un indicador de bash (usando PROMPT_FUNCTION) así:

function get_hg_prompt_prefix() {
    local APPLIED_COLOR=$1; shift
    local UNAPPLIED_COLOR=$1; shift
    local ALERT_COLOUR=$1; shift
    local TEXTCOLOR=$1; shift
    local mercurial_prompt_line="{{patches|join(:)|pre_applied(${APPLIED_COLOR})|post_applied(${TEXTCOLOR})|pre_unapplied(${UNAPPLIED_COLOR})|post_unapplied(${TEXTCOLOR})}\n\r}"
    local mercurial_status_prompt="{ ${ALERT_COLOUR}{status}${TEXTCOLOR}}"

    echo "$(hg prompt "${mercurial_prompt_line}" 2>/dev/null)$(hg prompt "${mercurial_status_prompt}" 2>/dev/null)"
}

function set_prompt() {
    bright='\[[01m\]'
    colors_reset='\[[00m\]'
    HOSTCOLOR=${colors_reset}='\[[34m\]'
    USERCOLOR=${colors_reset}='\[[01m\]'
    TEXTCOLOR=${colors_reset}='\[[32m\]'
    APPLIED_COLOR=${colors_reset}='\[[32m\]'
    UNAPPLIED_COLOR=${colors_reset}='\[[37m\]'
    ALERT_COLOUR=${colors_reset}='\[[31m\]'

    hg_status="$(get_hg_prompt_prefix $APPLIED_COLOR $UNAPPLIED_COLOR $ALERT_COLOUR $TEXTCOLOR)"
    ps1_prefix="${hg_status}$colors_reset($bright$(basename $VIRTUAL_ENV)$colors_reset) "
    PROMPTEND='$'
    PS1="${ps1_prefix}${USERCOLOR}\u${colors_reset}${TEXTCOLOR}@${colors_reset}${HOSTCOLOR}\h${colors_reset}${TEXTCOLOR} (\W) ${PROMPTEND}${colors_reset} "
}

PROMPT_COMMAND=set_prompt

En general, esto me muestra un mensaje de varias líneas que muestra información sobre el estado de hg, así como mi entorno virtual actual, con un aspecto (sin color) similar al siguiente:

buggy-wins.patch
 ! (saas) user@computer (~) $ 

El problema es que esto está arruinando el cálculo de la longitud del mensaje (¡creo!) y causando problemas extraños de ajuste del terminal y ubicación del cursor. Por ejemplo, en una terminal de 80 caracteres, este es el mensaje que veo (el carácter ** rodeado es la ubicación del cursor):

~) $ **a**nis) crose@chris-rose (~

En terminales lo suficientemente anchas como para mostrar el mensaje, el ajuste de línea ocurre mucho antes de lo que debería; aquí está la mayor cantidad de texto que puedo colocar en elprimerolínea del mensaje en una ventana de terminal de 108 caracteres de ancho (nuevamente, ** marca la ubicación de mi cursor):

 **(**advanis) crose@chris-rose (~) $ sdkfjlskdjflksdjff

Cuando la línea termina, sobrescribe el mensaje. Sin embargo, la segunda línea de entrada va hasta el borde del terminal y luego se ajusta correctamente.

Entonces, claramente algo está alterando el ancho del mensaje. ¿Cómo puedo hacer que bash determine la longitud de la cadena PS1 no de acuerdo con los códigos de escape ANSI, sino de acuerdo con la longitud real mostrada en el mensaje?

Respuesta1

bashse utiliza \[ \]para determinar la "longitud mostrada": el texto entre esos dos escapes se considera no imprimible y no se cuenta en la longitud total; todo lo demás lo es.

Parece haber un problema con sus variables: bright='\[[01m\]'en realidad no incluye un carácter ESC, por lo que [01mse imprime como texto normal pero no se cuenta en su longitud. Debería ser '\[\e[01m\]'. Lo mismo para todas las demás variables.


Relacionado:

  • En Bash, puedes colocarlo \$(hg_status)directamente $PS1, sin necesidad de un archivo PROMPT_COMMAND.

información relacionada