web-dev-qa-db-fra.com

L'invite de terminal ne s'emballe pas correctement

J'ai un problème où si je tape de très longues commandes dans bash, le terminal ne rendra pas ce que je tape correctement. Je m'attendrais à ce que si j'avais une commande comme la suivante:

username@someserver ~/somepath $ ssh -i /path/to/private/key
[email protected]

La commande doit s'afficher sur deux lignes. Au lieu de cela, il se terminera souvent et commencera à écrire par-dessus mon invite, un peu comme ceci:

[email protected] -i /path/to/private/key

Si je décide de revenir en arrière et de changer un argument, rien ne dit où le curseur apparaîtra, parfois au milieu de l'invite, mais généralement sur la ligne ci-dessus où je tape.

Un plaisir supplémentaire se produit lorsque Up à une commande précédente. J'ai essayé ceci dans gnome-terminal et terminator et sur i3 et Cinnamon. Quelqu'un a suggéré que c'était mon invite, alors voici:

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

Ctrll, reset et clear font tous ce qu'ils disent, mais quand je retape la commande ou Up les mêmes choses se produisent.

J'ai vérifié et checkwinsize est activé dans bash. Cela se produit sur 80x24 et d'autres tailles de fenêtre.

Est-ce juste une chose avec laquelle j'apprends à vivre? Y a-t-il un morceau de magie que je devrais connaître? Je me suis contenté d'utiliser une invite très courte, mais cela ne résout pas le problème.

185
Muricula

Les séquences non imprimables doivent être incluses entre \[ et \] . En regardant votre PS1 elle a une séquence non fermée après \W. Mais, la deuxième entrée est redondante et répète l'instruction précédente "1; 34" .

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

En tant que tel, cela aurait dû viser la coloration:

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

Garder le "original" cela devrait aussi fonctionner:

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

Éditer:

La raison de ce comportement est due au fait que bash pense que l'invite est plus longue qu'elle ne l'est réellement. À titre d'exemple simple, si l'on utilise:

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

L'invite est censée être de 8 caractères et non 1. En tant que tel, si la fenêtre du terminal est de 20 colonnes, après avoir tapé 12 caractères, elle est censée être de 20 et se termine. Cela est également évident si l'on essaie ensuite de faire un retour arrière ou Ctrl+u. Il s'arrête à la colonne 9.

Cependant, il ne démarre pas de nouvelle ligne à moins qu'il n'y en ait une sur la dernière colonne, par conséquent la première ligne est remplacée.

Si vous continuez à taper, la ligne doit passer à la ligne suivante après 32 caractères.

206
Runium

Il s'agit surtout de voir que la taille de la fenêtre supposée par le terminal n'est pas la même que la taille réelle de votre fenêtre. Si vous utilisez bash, vous pouvez essayer ceci.

$ shopt checkwinsize

Si vous n'obtenez pas

checkwinsize    on

Activez-le ensuite avec

$ shopt -s checkwinsize

Ensuite, essayez simplement d'exécuter une autre commande (comme ls) ou de redimensionner la fenêtre une fois, ce qui précède fonctionne pour moi à chaque fois.

Pour les systèmes Redhat en particulier, le problème est souvent causé par une mauvaise configuration ~/.bashrc ne pas appeler /etc/bashrc. Normalement, bash charge ~/.bashrc qui devrait appeler /etc/bashrc, qui contient par défaut shopt -s checkwinsize.

89
saketrp

J'ai lu une fois quelque part (je ne sais plus où) qu'en utilisant \001 et \002 au lieu de \[ et \] peut résoudre ce problème. Ça l'a fait pour moi.

Soit dit en passant, la définition de la PS1 n'a pas à être laide.

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
10
phil294

Comme mentionné dans d'autres réponses, les séquences non imprimables telles que \e[0;30m doit être entouré de \[...\].

De plus (et ce que je ne vois pas encore mentionné), il semble que \r\n doit être extérieur du \[...\] si vous avez une invite sur plusieurs lignes. Il m'a fallu quelques essais et erreurs pour finalement comprendre cela.

10
Geraden

Cela ressemble à un problème avec vos paramètres de variable d'environnement COLUMNS & LINES. Lorsque vous redimensionnez la fenêtre, elles sont généralement définies automatiquement par gnome-terminal (je crois), vous pouvez les forcer à être définies manuellement en exécutant la commande resize.

Exemple

Si je redimensionne mon gnome-terminal à 79x17, mes variables apparaissent comme suit:

$ echo $COLUMNS; echo $LINES
79
17

Je peux le forcer comme ça:

$ resize
COLUMNS=79;
LINES=17;
export COLUMNS LINES;
7
slm

Pour empêcher l'encapsulage, vous pouvez également augmenter le nombre de colonnes à l'aide, par ex.

stty columns 120
6
ishmael

Le même problème peut également être causé par l'utilisation de symboles Unicode larges (comme dans https://stackoverflow.com/a/34812608/1657819 ). Voici l'extrait de code à l'origine du problème (faites attention au $Green et $Red sont des chaînes de couleurs correctement échappées):

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 ne peut pas calculer la longueur correctement, donc le moyen le plus simple pourrait être d'échapper à 2 des trois parties de ces symboles larges.

FancyX='\[\342\234\]\227'
Checkmark='\[\342\234\]\223'
3
The Godfather

tput smam

Sur Ubuntu 19.10 dans un terminal Gnome, qui a TERM=xterm-256color, cela émet la séquence d'échappement exacte qui rend les lignes de retour à la ligne terminales:

tput smam

Vous pouvez voir ce que cette évasion est avec:

tput smam | hd

Réinitialisation de l'état du terminal avec:

reset

semble également avoir pour effet de définir tput smam.

La page de manuel:

man terminfo

documents smam et son opposé rmam:

       enter_am_mode   smam   SA   turn on automatic margins
       exit_am_mode    rmam   RA   turn off automatic margins

Notez cependant que certains terminaux n'ont pas cette capacité, par exemple à l'intérieur tmux nous avons TERM=screen-265color et smam n'apparaissent pas dans la liste des capacités:

infocmp

et donc tput smam n'imprime rien.

Je ne sais pas comment, mais QEMU a pu changer l'état de retour à la ligne de tmux alors que tput ne l'était pas .