Comment puis-je obtenir de longues lignes de commande pour passer à la ligne suivante?

108

Ce qui me frustre le plus depuis longtemps dans Ubuntu, c’est que je tape une commande sur la ligne de commande dont la largeur est supérieure à la largeur du terminal, au lieu d’enrouler une nouvelle ligne, elle revient à colonne 1 sur la même ligne et commence à écraser le début de ma ligne de commande. (Cela ne remplace pas réellement la commande, mais visuellement, il écrase le texte affiché).

C'est difficile à expliquer sans le voir, mais supposons que mon terminal ait 20 caractères de largeur (le mien ressemble plus à 120 caractères - mais à titre d'exemple), et je veux faire écho à l'alphabet anglais. Ce que je tape est ceci:

echo abcdefghijklmnopqrstuvwxyz

Mais à quoi ressemble mon terminal avant d’appuyer sur la touche est:

pqrstuvwxyzghijklmno

Quand je frappe entrer, il fait écho

abcdefghijklmnopqrstuvwxyz

donc je sais que la commande a été reçue correctement. Il vient juste de terminer ma frappe après le "o" et recommence sur la même ligne.

Ce à quoi je m'attendrais, si je tapais cette commande sur un terminal de 20 caractères de large serait la suivante:

echo abcdefghijklmno
pqrstuvwxyz

Fond: J'utilise bash comme shell et j'ai cette ligne dans mon ~ / .bashrc:

set -o vi

pour pouvoir naviguer en ligne de commande avec les commandes VI. J'utilise actuellement le serveur Ubuntu 10.10 et me connecte au serveur avec Putty.

Dans tout autre environnement dans lequel j'ai travaillé, si je tape une longue ligne de commande, une nouvelle ligne sera ajoutée sous la ligne sur laquelle je travaille lorsque ma commande dépasse la largeur du terminal et que je continue à taper, je peux voir ma commande. 2 lignes différentes. Mais aussi longtemps que je me souvienne d’utiliser Ubuntu, mes longues commandes n’occupent qu’une ligne.

Cela se produit également lorsque je reviens aux commandes précédentes de l'historique (j'appuie sur Echap, puis sur 'K' pour revenir aux commandes précédentes). Lorsque j'arrive à une commande précédente plus longue que la largeur du terminal, la ligne de commande obtient mutilé et je ne peux pas dire où je suis dans la commande.

Le seul moyen de contourner la commande longue que j'ai trouvée consiste à appuyer sur "Esc-V", ce qui ouvre la commande actuelle dans un éditeur de VI.

Je ne pense pas avoir quelque chose d'étrange dans mon fichier .bashrc. J'ai commenté la ligne "set -o vi", et j'ai toujours eu le problème.

J'ai téléchargé une nouvelle copie de Putty et je n'ai apporté aucun changement à la configuration - je viens de taper mon nom d'hôte pour me connecter, et j'ai toujours le problème, donc je ne pense pas que ce soit quelque chose avec Putty (sauf si je dois faire des changements de configuration)

Quelqu'un at-il eu ce problème et est-ce que quelqu'un peut penser à comment le résoudre?

Modifier

C'était mon fichier .bashrc. J'ai copié le même profil d'une machine à l'autre et j'ai utilisé des caractères spéciaux dans mon $ PS1 qui le jettent en quelque sorte. Je m'en tiens maintenant aux variables bash standard pour mon $ PS1.

Merci à @ ændrük pour le conseil sur le .bashrc!

... Fin Modifier ...

BrianH
la source
1
Pour que le problème ne soit pas causé par votre fichier .bashrc, je vous recommande de le remplacer temporairement par une copie de /etc/skel/.bashrc. N'oubliez pas que vous devez vous reconnecter pour que les modifications prennent effet et veillez à conserver une sauvegarde de votre propre fichier .bashrc.
ændrük
1
Quelle application de terminal utilisez-vous? Le comportement que vous décrivez n'est pas habituel, certainement pas par défaut.
João Pinto
Dans les shells dans lesquels j'ai travaillé (et dans Cisco CLI), vous pouvez également taper Ctrl-L pour afficher à nouveau la ligne que vous tapez, même si elle est hors écran. Dans votre cas, cela peut toujours produire la sortie cassée dont vous parlez, mais je serais curieux.
Belacqua
3
N'hésitez pas à créer une "réponse" expliquant la solution et à la marquer comme acceptée. Cela peut sembler un peu ridicule, mais une réponse appropriée permet de garder le site organisé et peut guider plus efficacement les personnes confrontées à des problèmes similaires à l'avenir.
ændrük
Selon cette réponse sur serverfault , utiliseztput smam
Samveen

Réponses:

136

Assurez-vous que tous les octets non imprimables de votre PS1 sont contenus dans celui-ci \[ \]. Sinon, bash les comptera dans la longueur de l'invite. Il utilise la longueur de l'invite pour déterminer le moment où la ligne doit être bouclée.

Par exemple, bash compte ici l’invite sur une largeur de 19 colonnes, alors que l’invite affichée par le terminal n’a qu’une largeur de 10 colonnes ( My prompten cyan et >en couleur par défaut):

PS1='\e[36mMy prompt\e[0m>'         # bash count: 19, actual: 10

alors qu'ici, l'invite n'a qu'une largeur de 10 colonnes, car elle ignore les octets entre le spécial \[et les \]échappements:

PS1='\[\e[36m\]My prompt\[\e[0m\]>' # bash count: 10, actual: 10

Par bonne pratique cependant, utilisez tputpour générer les fuites de terminal plutôt que de les coder en dur:

cyan=$(tput setaf 6) # \e[36m
reset=$(tput sgr0)   # \e[0m
PS1='\[$cyan\]My prompt\[$reset\]>'

Voir http://mywiki.wooledge.org/BashFAQ/053 , ainsi que http://wiki.bash-hackers.org/scripting/terminalcodes pour plus d'informations tput.

geirha
la source
3
Voilà une excellente explication du problème que la réponse acceptée ne fournit pas
Jamie Cook
Dans la dernière ligne de code PS1='...': pourquoi ne pas empêcher des guillemets simples $cyanet $resetde substitution?
Andrybak
2
@andrybak, ils empêchent $cyanet ne peuvent pas $resetêtre remplacés, mais PS1sont évalués chaque fois que l'invite est imprimée. Vous pouvez voir cela en essayant PS1='$var> 'puis en donnant vardiverses valeurs et voir comment l’invite change. Ensuite, essayez de PS1="$var> " remarquer que l’invite reste statique; $vara été élargi au cours de l'affectation, pas chaque fois PS1est évalué.
geirha
1
Ceci est incroyable. Merci énormément d'avoir posté cela! Cela facilite beaucoup l’échappement des crochets et le rend plus lisible.
Phyatt
Comment je fais ce travail PS1=${PS1}"\e]2;$@\a". J'ai essayéPS1=${PS1}"\[\e]2;\]$@\[\a\]"
Ramana Reddy
59

Je suppose que vous avez configuré votre PS1avec des couleurs, non?

Assurez-vous simplement que \[votre PS1citation précède votre jeu de couleurs.

Par exemple:

PS1='\[\e[0;32m\u@\w/:\[\e[m '
Wjandrea
la source
Mon PS1 était export PS1='^[[96m'$(hostname)'<^[[92m${PWD}^[[96m>^[[97m '- je l'utilise depuis longtemps - il est compatible KSH ...
BrianH
2
Sensationnel. J'utilise les invites de terminal depuis toujours et je n'ai jamais eu ce problème auparavant. Je n'aurais jamais compris ça. Merci.
bchurchill
3
utiliser \ [en utilisant des guillemets simples produit une barre oblique non intentionnelle. aussi, il devrait être utilisé] à la fin des caractères magiques, comme indiqué dans la réponse la mieux votée
igorsantos07
2
-1 ne fonctionne pas. Vous devez envelopper la section non imprimable avec \[au début et \]à la fin.
Wjandrea
@ igorsantos07 La double barre oblique inversée \\[était une faute de frappe provoquée par une modification. Je l'ai réparé.
Wjandrea
11

J'ai eu un problème similaire et j'ai finalement trouvé une solution simple.

Ajouter la ligne suivante dans votre .bashrcfichier:

COLUMNS=250

Puis tapez source ~/.bashrcpour obtenir l'effet désiré.

Deboshree
la source
Dans certains cas, tels que les subdivisions de terminateur étroit, le problème ne réside pas dans les caractères de couleur imminents, mais simplement dans une valeur COLUMNS incorrecte. Cette réponse m'a fait sortir d'un trou très dérangeant!
Carles Sala
1
Se déconnecter est inutile. Faire source .bashrc. Votre message sera mis à jour immédiatement
Sergiy Kolodyazhnyy
1
Je me suis rendu compte que je n'avais pas setwinsizeconfiguré shopt pour ma bash et que la mise à jour de COLUMNS n'était donc pas correcte. Voir unix.stackexchange.com/a/167911/8337
rogerdpack le
1
J'ai export COLUMNS=250suivi export TERM=xtermet c'était heureux.
Philip Kearns
5

J'ai eu le même problème avec une invite de couleur personnalisée, même si je contenais des codes de couleur à l'intérieur \[et des \]délimiteurs. Il s'avère que bash a des problèmes pour faire écho aux couleurs de l'intérieur d'une fonction . J'ai fini par utiliser uniquement des variables pour mon invite, et bien que mon .bashrc soit un peu moins élégant, tout fonctionne bien maintenant.

reentim
la source
Si quelqu'un lit encore cela, il est en fait possible d'échapper aux couleurs d'une fonction. Voir cette réponse sur la question liée.
Wjandrea
3

Une chose simple à faire serait d’ajouter la ligne suivante avant de configurer la PS1:

stty columns 1000

Par exemple,

stty columns 1000
PS1='\[\e[0;32m\u@\w/:[\e[m '

Cependant, cela affecte d'autres commandes Unix comme ls et man.

Gennady
la source
1
Cela fonctionne sous OSX.
Raskhadafi
4
Cela affecte également vim. S'il vous plaît ne pas utiliser cela.
demi
0

J'ai eu ce problème quand je suis connecté à tmux. Le problème était que j'avais une ipythonsession en arrière-plan ( ctrl + z) et que, d'une manière ou d'une autre, la rupture de la ligne était rompue. Dès que je l'ai terminé ( fg, ctrl+d+d) mon terminal a commencé à fonctionner correctement

Donc, recherchez les invites interactives arrêtées.

Ciprian Tomoiagă
la source
0

Donc, je viens d'avoir le même problème avec une légère torsion sur elle et j'ai pensé partager ma solution aussi, juste pour ajouter ma petite nuance: D

Ma PS1 initiale était

PS1="\[\033[01;32m\]\u\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$"

Le problème que j'ai eu était que j'essayais de changer le titre de mon terminal ainsi que l'invite de commande. Pour ce faire, j'ai ajouté \[\033]0;\]Title\aà la variable PS1 .

Alors maintenant, ma PS1 était:

PS1="\[\033[01;32m\]\u\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$\[\033]0;\]Title\a"

Cette foutue la ligne d'emballage pour moi. J'ai finalement compris que Bash ne semble pas aimer avoir \aà la fin. Pour contourner cela, j'ai mis le titre dans une variable, qui semblait le réparer.

TITLE="\033]0;Title\a"
PS1="\[\033[01;32m\]\u\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$\[$TITLE\]"
Ciarán J. Hagen
la source
0

\[et \]n'a pas fonctionné pour moi. J'imagine que la manière dont j'ai généré l'invite (à partir d'un programme externe) était différente, ou parce que mon invite était "dynamique".

Après la lecture de ce que je trouve que vous pouvez réellement échapper aux codes de couleurs avec les 0x01et 0x02octets.

Par exemple, j'utilise une version spéciale de Chalk et j'emballe les couleurs en utilisant ceci:

const Chalk = require('@nasc/chalk');

const chalk = new Chalk.constructor({
  wrapper: {
    pre: '\1',
    post: '\2',
  }
});
mpen
la source