Cómo mostrar caracteres de control (^C, ^D, ^[, ...) de manera diferente en el shell

Cómo mostrar caracteres de control (^C, ^D, ^[, ...) de manera diferente en el shell

Cuando escribe caracteres de control en el shell, se muestran usando lo que se llama "notación de intercalación". Escape, por ejemplo, se escribe como ^[en notación de intercalación.

Me gusta personalizar mi shell bash para que se vea genial. Por ejemplo, he cambiado mi imagen PS1y PS2me he coloreado. Ahora quiero que los personajes de control tengan una apariencia única para hacerlos más distinguibles de los personajes normales.

$ # Here I type CTRL-C to abort the command.
$ blahblah^C
          ^^ I want these two characters to be displayed differently

¿Hay alguna manera de hacer que mi shell resalte los caracteres de control de manera diferente?

¿Es posible hacer que se muestren en negrita o tal vez hacer que aparezcan en colores diferentes a los del texto normal?

estoy usandointentoshell aquí, pero no etiqueté la pregunta bashporque tal vez haya una solución que se aplique a muchos shells diferentes.

Notaque no sé en qué nivel se resaltan los personajes de control. Primero pensé que estaba en el propio caparazón. Ahora he oído que eslínea de lecturaque controla cómo están los personajes de control en caparazones comointento. Entonces la pregunta ahora está etiquetada con readliney todavía estoy buscando respuestas.

Respuesta1

Cuando presionas Ctrl+X, tu emulador de terminal escribe el byte 0x18 en el lado maestro del par de pseudo-terminales.

Lo que sucede a continuación depende de cómo esté configurada la disciplina de la línea tty (un módulo de software en el kernel que se encuentra entre el lado maestro (bajo el control del emulador) y el lado esclavo (con el que interactúan las aplicaciones que se ejecutan en el terminal)).

Un comando para configurar eso.disciplina de línea ttyes el sttycomando.

Cuando se ejecuta una aplicación tonta como catesa, no se da cuenta y no le importa si su entrada estándar es una terminal o no, la terminal está en modo predeterminado.canónicomodo donde la disciplina de línea tty implementa un crudoeditor de línea.

Algunas aplicaciones interactivas que necesitan más que esoeditor de líneaPor lo general, cambie esas configuraciones al iniciar y restáurelas al salir. conchas modernas,a su avisoson ejemplos de tales aplicaciones. Implementan su propio editor de líneas más avanzado.

Normalmente, mientras ingresa una línea de comando, el shell coloca la disciplina de línea tty en ese modo, y cuando presiona Intro para ejecutar el comando actual, el shell restaura el modo tty normal (como estaba en vigor antes de emitir el mensaje).

Si ejecuta el stty -acomando, verá la configuración actual en uso para elaplicaciones tontas. Es probable que veas las icanonconfiguraciones echoy echoctlhabilitadas.

Lo que eso significa es que:

  • icanon: ese editor de líneas crudas está habilitado.
  • echo: los caracteres que escribe (que el emulador de terminal escribe en el lado maestro) sonhizo ecoatrás (disponible para lectura mediante el emulador de terminal).
  • echoctl: en vez de serhizo ecoAsí, los personajes de control sonhizo ecocomo ^X.

Entonces, digamos que escribes A B Backspace-aka-Ctrl+H/? C Ctrl+X Backspace Return.

Su emulador de terminal enviará: AB\bC\x18\b\r. La disciplina de líneaecoback: AB\b \bC^X\b \b\b \b\r\ny una aplicación que lee la entrada del lado esclavo ( /dev/pts/x) leerá AC\n.

Todo lo que ve la aplicación es AC\n, y solo cuando presiona, Enterpor lo que no puede tener ningún control sobre la salida allí ^X.

Lo notarás poreco, el primero ^H( ^?con algunos terminales, consulte la eraseconfiguración) resultó en \b \bser enviado de regreso al terminal. Esa es la secuencia para mover el cursor hacia atrás, sobrescribir con espacio, mover el cursor hacia atrás nuevamente, mientras que la segunda ^Hresultó en \b \b\b \bborrar esos dos caracteres ^y .X

El ^Xpropio (0x18) se estaba traduciendo hacia ^y Xpara la salida. Por ejemplo B, no llegó a la aplicación porque lo eliminamos con Retroceso.

\r(también conocido como ^M) se tradujo a \r\n( ^M^J) para eco y \n( ^J) para la aplicación.

Entonces, ¿cuáles son nuestras opciones para aquellosmudoaplicaciones:

  • desactivar echo( stty -echo). Eso cambia efectivamente la forma en que se repiten los caracteres de control, al... no hacer eco de nada. Realmente no es una solución.
  • desactivar echoctl. Eso cambia la forma en que se repiten los caracteres de control (que no sean ^H, ^M... y todos los demás utilizados por el editor de líneas). ellos son entonceshizo ecocomo es. Es decir, por ejemplo, el carácter ESC se envía como el byte \e( ^[/ 0x1b) (que el terminal reconoce como el inicio de una secuencia de escape), ^Gusted envía un \a(un BEL, que hace que su terminal emita un pitido)... No es una opción .
  • deshabilite el editor de líneas crudas ( stty -icanon). Realmente no es una opción ya que las aplicaciones básicas serían mucho menos utilizables.
  • editar el código del kernel para cambiar el comportamiento de la disciplina de línea tty para queecoSe envía un carácter de control \e[7m^X\e[men lugar de solo ^X(aquí \e[7mse suele habilitar vídeo inverso en la mayoría de terminales).

Una opción podría ser usar un contenedor como rlwrapese, que es un truco sucio para agregar un editor de líneas elegante a aplicaciones tontas. En efecto, ese contenedor intenta reemplazar read()mensajes de correo electrónico simples desde el dispositivo terminal con llamadas al editor de líneas readline (que cambian el modo de la disciplina de línea tty).

Yendo aún más lejos, incluso podrías probar soluciones comoÉsteque secuestra todas las entradas del terminal para pasar por el editor de líneas de zsh (que resalta ^Xs en video inverso) dependiendo de la función de pantalla GNU :exec.

Ahora, para las aplicaciones que implementan su propio editor de líneas, depende de ellas decidir cómoecoestá hecho. bashusa readline para aquello que no tiene ningún soporte para personalizar cómo se repiten los caracteres de control.

Para zsh, ver:

info --index-search='highlighting, special characters' zsh

zshresalta los caracteres no imprimibles de forma predeterminada. Puede personalizar el resaltado con, por ejemplo:

zle_highlight=(special:fg=white,bg=red)

Para resaltar en blanco sobre rojo esos caracteres especiales.

Sin embargo, la representación de texto de esos caracteres no se puede personalizar.

En una configuración regional UTF-8, 0x18 se representará como ^X, \u378, \U7fffffff(dos puntos de código Unicode no asignados) como <0378>, <7FFFFFFF>, \u200b(un carácter Unicode que no se puede imprimir) como <200B>.

\x80en una configuración regional iso8859-1 se representaría como ^�... etc.

Respuesta2

Normalmente tengo este código en mi archivo .bashrc:

function get_exit_status()
{
        local code=$?
        if [ $code -ne 0 ]
        then
                printf $'\001\033[31m\002'"($code)"$'\001\033[0m\002'" "
        fi
}

y luego llamo a esta función en mi PS1

PS1='\u@\h \w $(get_exit_status)'

Con esto, si presionas ^C lo verás en tu mensaje

I@mycomputer ~ ^C
I@mycomputer ~ (130)

Se solicitarán todos los códigos de estado de salida que no sean "0".

información relacionada