Superposición del historial del cliente bash personalizado

Superposición del historial del cliente bash personalizado

Estoy escribiendo un cliente para realizar varias tareas en el servidor Zimbra a través de ssh y me encontré con un pequeño problema. Aquí está el código:

#!/bin/bash
set -e
export PATH=/usr/bin:/bin:/usr/sbin:/sbin
export HISTCONTROL=ignoreboth

# History management
if [ -f $HOME/.zmcli_history ]; then
  history -r $HOME/.zmcli_history
else
  touch $HOME/.zmcli_history
  history -r $HOME/.zmcli_history
fi
trap "history -a $HOME/.zmcli_history && echo -e '\nExiting now.\n'" exit

# Styling
yellow='[33m'
bold='[1m'
off='[0m'

echo

# Client
while :; do
  read -ep "$bold${yellow}zimbra_cli[${off}server_domain$bold${yellow}]> $off" comm
  history -s "$comm"
done

NOTA: si ejecuta este script, creará el archivo histórico (.zmcli_history) en su directorio de inicio.

Todo funciona según lo previsto y el historial está ahí, pero a menudo la parte de algún comando anterior (normalmente largo) permanece a medida que continúo desplazándome por el historial. Esa parte del comando actúa como parte del mensaje para el resto de la sesión, a menos que presione CTRL+L, lo que borra la pantalla y la restablece a la normalidad. He leído muchas publicaciones que ayudaron a las personas que tenían este problema en su terminal bash. Su problema fue que PS1 estaba formateada incorrectamente y bash se confundió acerca de la longitud de la cadena de solicitud. Probablemente sea algo similar aquí, pero esas soluciones no funcionan, porque el comando de lectura no puede usar esos caracteres de escape como echo (\e).

Logré encontrar una manera de escapar de las secuencias de colores usando escapes literales (CTRL+V ESCAPE en modo de inserción vim). Entonces los colores funcionan, pero estoy atrapado con este problema histórico.

Cosas que he probado:

  • sustitución de comandos :: escriba y escape los códigos de color de una manera que echo -e pueda imprimirlos, y luego repita en el comando de lectura $(echo -e '\e[33m'). Sigo viendo los colores, pero no ayudó con el problema del historial.
  • agregando escape [ y ] alrededor de los códigos de color
  • colocar todo el mensaje con códigos de color en un comando de eco separado que viene antes del comando de lectura. La desventaja es que no puedo desactivar el formato hasta después del comando de lectura (en otro eco), lo que significa que todo el mensaje y el comando estarán en negrita y en color. Además, si presiono CTRL+L ahora, incluso el mensaje se borrará y solo me quedará el cursor.

Finalmente, como no puedo eliminar el historial, intenté eliminar los colores. Pero luego resulta imposible diferenciar rápidamente entre comandos y resultados.

Puede replicar el problema iniciando el script e ingresando entre 10 y 15 comandos largos (galimatías). Después de eso, intenta desplazarte hacia arriba y hacia abajo por el historial y verás de qué estoy hablando.

¿Alguien sabe una manera de hacer que esto funcione?

Respuesta1

Tu guión,como están las cosas, no me permitió replicar el problema. Solo después de habilitar los colores y dicha línea de lectura comenzaron a confundirse. Para que conste, habilité estas cosas con

# Styling
yellow=$'\e[33m'
bold=$'\e[1m'
off=$'\e[0m'

Y es verdad \[y \]no ayuda.lo hacen en caso dePS1.

Pero luego encontréesta respuesta. Se lee

Abrí info readliney encontré:

[…]
Las aplicaciones pueden indicar que el mensaje contiene caracteres que no ocupan espacio físico en la pantalla cuando se muestran poniendo entre corchetes una secuencia de dichos caracteres con los marcadores especiales RL_PROMPT_START_IGNOREy RL_PROMPT_END_IGNORE(declarados en readline.h. Esto se puede usar para incrustar secuencias de escape específicas del terminal en los mensajes.

Como digo texto que busco RL_PROMPT_START_IGNOREy RL_PROMPT_END_IGNOREdefinición readline.hy encontré a continuación:

/* Definitions available for use by readline clients. */
#define RL_PROMPT_START_IGNORE  '\001'
#define RL_PROMPT_END_IGNORE    '\002'

Esto me llevó a lo siguiente:

# Styling
yellow=$'\1\e[33m\2'
bold=$'\1\e[1m\2'
off=$'\1\e[0m\2'

Funciona perfectamente.

información relacionada