Cuando escribe caracteres de control en el shell, se muestran utilizando lo que se denomina "notación de intercalación". Escape, por ejemplo, se escribe como ^[
en notación de intercalación.
Me gusta personalizar mi bash shell para que se vea genial. Por ejemplo, he cambiado mi PS1
y PS2
para colorear. Ahora quiero que los personajes de control tengan una apariencia única también para que sean 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 muestre en negrita o tal vez hacer que aparezcan en diferentes colores del texto normal?
Estoy usando bash shell aquí, pero no etiqueté la pregunta bash
porque quizás haya una solución que se aplique a muchos shells diferentes.
Tenga en cuenta que no sé en qué nivel tiene lugar el resaltado de los caracteres de control. Primero pensé que estaba en el caparazón mismo. Ahora he oído que es readline que controla cómo los personajes de control están en shells como bash . Así que la pregunta ahora está etiquetada readline
y todavía estoy buscando respuestas.
bash
estáreadline
manejando esas cosas, y para la mayoría de los demás es el controlador tty.vi
, yless
con frecuencia los caracteres de control resaltado diferente del texto normal. Editaré la pregunta con esta información. ¡Gracias!zsh
cuál lo hace fuera de la caja.Respuestas:
Cuando presiona Ctrl+X, su emulador de terminal escribe el byte 0x18 en el lado maestro del par pseudo-terminal.
Lo que sucede a continuación depende de cómo se configura la disciplina de línea tty (un módulo de software en el núcleo 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 esa disciplina de línea tty es el
stty
comando.Cuando ejecuta una aplicación tonta como
cat
esa no es consciente y no le importa si su stdin es una terminal o no, la terminal está en un modo canónico predeterminado donde la disciplina de línea tty implementa un editor de línea cruda .Algunas aplicaciones interactivas que necesitan más que ese editor de línea cruda suelen cambiar esa configuración al inicio y restaurarla al salir. Los proyectiles modernos, a su solicitud, son ejemplos de tales aplicaciones. Implementan su propio editor de línea más avanzado.
Por lo general, mientras ingresa una línea de comando, el shell coloca la disciplina de línea tty en ese modo, y cuando presiona enter para ejecutar el comando actual, el shell restaura el modo tty normal (como estaba vigente antes de emitir el aviso).
Si ejecuta el
stty -a
comando, verá la configuración actual en uso para las aplicaciones tontas . Es probable que vea elicanon
,echo
yechoctl
los ajustes que se habilitó.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) se repiten (están disponibles para su lectura por el emulador de terminal).echoctl
: en lugar de repetirse como asis, los caracteres de control se repiten como^X
.Entonces, digamos que escribes A B Backspace-aka-Ctrl+H/? C Ctrl+X Backspace Return.
El emulador de terminal enviará:
AB\bC\x18\b\r
. La disciplina de línea hará eco :AB\b \bC^X\b \b\b \b\r\n
y se leerá una aplicación que lee la entrada del lado esclavo (/dev/pts/x
)AC\n
.Todo lo que ve la aplicación es
AC\n
, y solo cuando presiona Enterpara que no pueda tener ningún control en la salida^X
allí.Notarás que para echo , el primero
^H
(^?
con algunos terminales, ver laerase
configuración) resultó en\b \b
ser enviado de vuelta 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 el segundo^H
resultó en\b \b\b \b
borrar esos dos^
yX
caracteres.El
^X
(0x18) en sí mismo se estaba traduciendo hacia^
yX
para la salida. Al igualB
, no llegó a la aplicación, ya que la eliminamos con Retroceso.\r
(aka^M
) se tradujo a\r\n
(^M^J
) para echo, y\n
(^J
) para la aplicación.Entonces, ¿cuáles son nuestras opciones para esas aplicaciones tontas ?
echo
(stty -echo
). Eso cambia efectivamente la forma en que se hacen eco de los caracteres de control, al ... no hacer eco de nada. Realmente no es una solución.echoctl
. Eso cambia la forma en que se hacen eco los caracteres de control (que no sean^H
,^M
... y todos los demás utilizados por el editor de línea). Luego se repiten tal cual. Es decir, por ejemplo, el carácter ESC se envía como el byte\e
(^[
/0x1b
) (que es reconocido como el inicio de una secuencia de escape por el terminal),^G
usted envía un\a
(un BEL, haciendo que su terminal emita un pitido) ... No es una opción .stty -icanon
). No es realmente una opción, ya que las aplicaciones crudas serían mucho menos utilizables.\e[7m^X\e[m
lugar de solo^X
(aquí\e[7m
generalmente se habilita el video inverso en la mayoría de los terminales).Una opción podría ser usar un contenedor como
rlwrap
ese es un truco sucio para agregar un editor de línea elegante a aplicaciones tontas. Ese envoltorio en efecto intenta reemplazar los mensajes simplesread()
desde el dispositivo terminal a las llamadas al editor de línea readline (que cambian el modo de la disciplina de línea tty).Yendo aún más lejos, incluso podría probar soluciones como esta que secuestra todas las entradas del terminal para pasar por el editor de línea de zsh (que resalta
^X
s en video inverso) confiando en la:exec
función de la pantalla GNU .Ahora, para las aplicaciones que implementan su propio editor de línea, depende de ellos decidir cómo se hace el eco .
bash
usa readline para aquello que no tiene soporte para personalizar cómo se repiten los caracteres de control.Para
zsh
ver:zsh
resalta caracteres no imprimibles de forma predeterminada. Puede personalizar el resaltado con, por ejemplo:Para resaltar blanco sobre rojo para esos caracteres especiales.
Sin embargo, la representación de texto de esos caracteres no es personalizable.
En una localización UTF-8, 0x18 será mostrado como
^X
,\u378
,\U7fffffff
(dos puntos de código Unicode sin asignar) como<0378>
,<7FFFFFFF>
,\u200b
(un carácter Unicode imprimible no-realidad) como<200B>
.\x80
en un entorno local iso8859-1 se representaría como^�
... etc.fuente
Usualmente tengo este código en mi archivo .bashrc:
y luego llamo a esta función en mi PS1
Con esto, si presiona ^ C, lo verá en su mensaje
Se le solicitarán todos los códigos de estado de salida que no sean "0".
fuente