El indicador de terminal no se ajusta correctamente

172

Tengo un problema en el que si escribo comandos muy largos en bash, el terminal no mostrará lo que estoy escribiendo correctamente. Esperaría eso si tuviera un comando como el siguiente:

username@someserver ~/somepath $ ssh -i /path/to/private/key
myusername@something.someserver.com

El comando debe representarse en dos líneas. En cambio, a menudo se ajustará y comenzará a escribir sobre la parte superior de mi mensaje, algo así:

myreallylongusername@something.somelongserver.comh -i /path/to/private/key

Si decido regresar y cambiar algún argumento, no se sabe dónde aparecerá el cursor, a veces en el medio de la solicitud, pero generalmente en la línea de arriba donde estoy escribiendo.

Diversión adicional sucede cuando cuando Upa un comando anterior. He intentado esto en gnome-terminal y terminator y en i3 y Cinnamon. Alguien sugirió que era mi mensaje, así que aquí está:

\[\033[01;32m\]\u:\[\033[01;34m\] \W\033[01;34m \$\[\033[00m\]

Ctrll, resety cleartodos hacen lo que dicen, pero cuando vuelvo a escribir el comando o Upsucede lo mismo.

Lo comprobé y checkwinsizeestá habilitado en bash. Esto sucede en 80x24 y otros tamaños de ventana.

¿Es esto algo con lo que aprendo a vivir? ¿Hay alguna pieza de magia que debería saber? Me he conformado con usar un mensaje muy breve, pero eso no soluciona el problema.

Muricula
fuente
1
Entonces, usar el comando lo env -i bash --norcarregla. Los $ COLUMNS y $ LINES coinciden. ¿Eso significa que hay algo divertido con mi .bashrc?
Muricula
Así que comenté mi .bashrc y terminé aislando mi solicitud como la parte problemática, específicamente la sintaxis de coloración involucrada. ¿Qué hay de malo con la PS1 anterior?
Muricula
1
\[\033[01;32m\]\u: \[\033[01;34m\]\W \[\033[01;34m\] \$ \[\033[0m\]parece evitar la rareza en el comportamiento - pero no sé si se respeta su pronta originales por completo ...
1
Según esta respuesta en serverfault , usetput smam
Samveen

Respuestas:

189

Las secuencias no imprimibles deben incluirse en \[y\] . Mirando tu PS1 , tiene una secuencia no cerrada después \W. Pero, la segunda entrada es redundante y repite la declaración anterior "1; 34" .

\[\033[01;32m\]\u:\[\033[01;34m\] \W\033[01;34m \$\[\033[00m\]
                  |_____________|               |_|
                         |                       |
                         +--- Let this apply to this as well.

Como tal, esto debería haber pretendido colorear:

\[\033[1;32m\]\u:\[\033[1;34m\] \W \$\[\033[0m\]
                               |_____|
                                  |
                                  +---- Bold blue.

Mantener el "original" también debería funcionar:

\[\033[1;32m\]\u:\[\033[1;34m\] \W\[\033[1;34m\] \$\[\033[0m\]
                                  |_|         |_|
                                   |           |
                                   +-----------+-- Enclose in \[ \]

Editar:

La razón del comportamiento es porque bashcree que el mensaje es más largo de lo que realmente es. Como un simple ejemplo, si uno usa:

PS1="\033[0;34m$"
       1 2345678

Se cree que la solicitud tiene 8 caracteres y no 1. Como tal, si la ventana del terminal tiene 20 columnas, después de escribir 12 caracteres, se cree que tiene 20 y se ajusta. Esto también es evidente si uno intenta hacer retroceso o Ctrl+u. Se detiene en la columna 9.

Sin embargo, tampoco comienza una nueva línea a menos que haya una en la última columna, como resultado se sobrescribe la primera línea.

Si uno sigue escribiendo, la línea debe ajustarse a la siguiente línea después de 32 caracteres.

Runium
fuente
Si usted, o alguien, tiene una explicación de qué exactamente en la secuencia original hizo que la línea se repita sobre sí misma, me interesaría saber eso. También +1 por cómo mostraste esto visualmente.
1
@ illuminÉ: No he mirado la fuente, pero agregué una actualización con una nota sobre el comportamiento de la observación.
Runium
En caso de que tenga algún problema, puede usar este sitio web para crear uno nuevo - bashrcgenerator.com
divinedragon
Esto es increíble, gracias @Runium, ¿te importaría compartir cómo lo sabías? Me encantaría encontrar documentación sobre esto.
nycynik
2
@nycynik: Observación. Supongo que lo más cercano a la documentación sobre esto es el código fuente ...
Runium
84

Se trata principalmente de que el tamaño de la ventana asumido por el terminal no es el mismo que el tamaño real de la ventana. Si está utilizando bash, puede probar esto.

$ shopt checkwinsize

Si no consigues

checkwinsize    on

Luego actívelo con

$ shopt -s checkwinsize

Luego, simplemente intente ejecutar otro comando (como ls) o cambiar el tamaño de la ventana una vez, lo anterior funciona para mí cada vez.

Para los sistemas Redhat en particular, el problema a menudo es causado por una configuración ~/.bashrcincorrecta de no llamar /etc/bashrc. Normalmente, bash carga lo ~/.bashrcque se espera que llame /etc/bashrc, que por defecto contiene shopt -s checkwinsize.

saketrp
fuente
Tuve el mismo problema con OS X, aparentemente si llamas a "login" para iniciar tu terminal, comienza bash de una manera que dice / etc / bashrc, pero si solo llamas directamente a bash, el ~ / .bashrc no fuente de las cosas de forma predeterminada para que obtenga el efecto de ajuste extraño. ¡Gracias!
rogerdpack
Esto funcionó para mí también. Los colores no estaban en este servidor en particular, llamando correcto /etc/bashrc, todo lo demás era bueno ... resulta que esta es la causa de los problemas de ajuste.
dhaupin
Ver también unix.stackexchange.com/a/61608/2221
astrojuanlu
1
Parece una buena solución. Pero no funciona en mi sesión ssh. No estoy seguro de por qué. Ejecuté el comando shopt -s checkwinsizeen la sesión ssh. Pero la envoltura persiste.
Qiang Xu
Este fue precisamente mi problema: un usuario .bashrc no estaba llamando a / etc / bashrc, por lo que era un desastre.
Sobrique
9

Como se menciona en otras respuestas, las secuencias no imprimibles, como las \e[0;30mque se deben envolver \[...\].

Además (y lo que no veo mencionado todavía) es que \r\ndebería estar fuera de \[...\]si tienes un mensaje de varias líneas. Me tomó algo de prueba y error finalmente resolver eso.

Geraden
fuente
8

Una vez leí en alguna parte (ya no sé dónde) que usando \001y en \002lugar de \[y \]puedo resolver este problema. Lo hizo por mi.

Por cierto, definir PS1 no tiene que verse feo.

green="\001$(tput setaf 2)\002"
blue="\001$(tput setaf 4)\002"
dim="\001$(tput dim)\002"
reset="\001$(tput sgr0)\002"

PS1="$dim[\t] " # [hh:mm:ss]
PS1+="$green\u@\h" # user@host
PS1+="$blue\w\$$reset " # workingdir$

export PS1
unset green blue dim reset
phil294
fuente
2
Mi PS1 llama a un comando que imprime secuencias de escape que causan el problema de OP. Solo esta solución me soluciona el problema.
RickMeasham
7

Esto suena como un problema con sus COLUMNSy LINESmedio ambiente ajustes variables. Cuando cambia el tamaño de la ventana, generalmente se configuran automáticamente mediante gnome-terminal (creo), puede forzarlos a configurarse manualmente emitiendo el comando resize.

Ejemplo

Si cambio el tamaño de mi terminal gnome a 79x17, mis variables se muestran así:

$ echo $COLUMNS; echo $LINES
79
17

Puedo forzarlo así:

$ resize
COLUMNS=79;
LINES=17;
export COLUMNS LINES;
slm
fuente
1
Interesante, pero no ayuda.
Muricula
1
Esto solucionó mi problema de que no estaba ajustando las líneas correctamente después de ejecutar el comando "pantalla". ¡¡Gracias!!
Nukeguy
5

Para evitar el ajuste, también puede aumentar el número de columnas utilizando, por ejemplo,

stty columns 120
ismael
fuente
1
no es una muy buena idea, lo arruinó vim brutalmente
phil294
3

También se puede causar el mismo problema al usar símbolos Unicode anchos (como https://stackoverflow.com/a/34812608/1657819 ). Aquí está el fragmento de la causa del problema (la mente el $Greeny $Redse escapó correctamente las cadenas de color):

FancyX='\342\234\227'
Checkmark='\342\234\223'


# Add a bright white exit status for the last command
PS1="$White\$? "
# If it was successful, print a green check mark. Otherwise, print
# a red X.
if [[ $Last_Command == 0 ]]; then
    PS1+="$Green$Checkmark "
else
    PS1+="$Red$FancyX "
fi

Bash no puede calcular la longitud correctamente, por lo que la forma más fácil podría ser escapar de 2 de las tres partes de esos símbolos anchos.

FancyX='\[\342\234\]\227'
Checkmark='\[\342\234\]\223'
El Padrino
fuente
Tiene sentido. Lo que supongo es que bash cuenta personajes. Debido a que la X toma un carácter pero está escrito como 3, entonces uno necesita encerrar 2 de ellos para arreglar el conteo. La respuesta de @blauhirn también explica cómo hacerlo en una función con \001y \002.
akostadinov
Para su información, así es como se da cuenta de cómo generar caracteres Unicode de varios bytes en este formato: stackoverflow.com/a/602924/520567
akostadinov