Il prompt dei terminali non si avvolge correttamente


172

Ho un problema in cui se digito comandi molto lunghi in bash il terminale non visualizzerà ciò che sto digitando correttamente. Mi aspetto che se avessi un comando simile al seguente:

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

Il comando dovrebbe eseguire il rendering su due righe. Invece spesso si avvolge e inizia a scrivere sopra il mio prompt, un po 'così:

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

Se decido di tornare indietro e cambiare qualche argomento, non c'è modo di dire dove apparirà il cursore, a volte nel mezzo del prompt, ma di solito sulla riga sopra dove sto scrivendo.

Divertimento aggiuntivo si verifica quando Upa un comando precedente. L'ho provato sia in gnome-terminal che in terminator e su i3 e Cinnamon. Qualcuno ha suggerito che fosse il mio suggerimento, quindi eccolo qui:

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

Ctrll, resete cleartutti fanno ciò che dicono, ma quando digito nuovamente il comando o Upsuccede le stesse cose.

Ho controllato ed checkwinsizeè abilitato in bash. Questo accade su 80x24 e altre dimensioni di finestre.

È solo qualcosa con cui imparo a convivere? C'è qualche pezzo di magia che dovrei sapere? Ho deciso di utilizzare solo un prompt molto breve, ma questo non risolve il problema.


1
Quindi l'uso del comando lo env -i bash --norcrisolve. La partita $ COLUMNS e $ LINES. Significa che c'è qualcosa di divertente nel mio .bashrc?
Muricula,

Così ho commentato il mio .bashrc e ho finito per isolare il mio prompt come parte problematica, in particolare la sintassi della colorazione coinvolta. Cosa c'è che non va nella PS1 sopra?
Muricula,

1
\[\033[01;32m\]\u: \[\033[01;34m\]\W \[\033[01;34m\] \$ \[\033[0m\]sembra evitare la stranezza nel comportamento - ma non so se rispetta completamente il tuo prompt originale ...

1
Come da questa risposta su serverfault , usatput smam
Samveen il

Risposte:


189

Le sequenze non stampabili devono essere racchiuse tra \[e\] . Guardando la tua PS1 ha una sequenza non rivelata dopo \W. Ma la seconda voce è ridondante e ripete la precedente frase "1; 34" .

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

Come tale, ciò avrebbe dovuto intendere la colorazione:

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

Mantenere l' originale dovrebbe funzionare anche:

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

Modificare:

Il motivo del comportamento è perché bashritiene che il prompt sia più lungo di quanto non sia in realtà. A titolo di esempio, se si usa:

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

Si ritiene che il prompt sia composto da 8 caratteri e non 1. In quanto tale, se la finestra del terminale è di 20 colonne, dopo aver digitato 12 caratteri, si ritiene che sia composta da 20 caratteri e si avvolge. Ciò è anche evidente se si prova a fare backspace o Ctrl+u. Si ferma alla colonna 9.

Tuttavia, non avvia anche una nuova riga a meno che non si trovi sull'ultima colonna, di conseguenza la prima riga viene sovrascritta.

Se si continua a digitare la riga dovrebbe passare alla riga successiva dopo 32 caratteri.


Se hai - o qualcuno - hai una spiegazione su cosa esattamente nella sequenza originale abbia causato la ripetizione della linea su se stessa, sarei interessato a saperlo. Inoltre +1 per come l'hai mostrato visivamente.

1
@ illuminÉ: non ho esaminato la fonte, ma ho aggiunto un aggiornamento con una nota sul comportamento dell'osservazione.
Runium,

Nel caso in cui dovessi riscontrare problemi, puoi utilizzare questo sito Web per crearne uno nuovo - bashrcgenerator.com
divinedragon,

È fantastico, grazie @Runium - ti dispiacerebbe condividere come lo sapevi? Mi piacerebbe trovare un po 'di documentazione su questo.
nycynik,

2
@nycynik: osservazione. Immagino che il più vicino alla documentazione su questo sia il codice sorgente ...
Runium,

84

Ha principalmente a che fare con la dimensione della finestra assunta dal terminale non uguale alla dimensione della finestra effettiva. Se stai usando bash, puoi provare questo.

$ shopt checkwinsize

Se non capisci

checkwinsize    on

Quindi attivalo con

$ shopt -s checkwinsize

Quindi prova a eseguire un altro comando (come ls) o a ridimensionare la finestra una volta, quanto sopra funziona per me ogni volta.

Soprattutto per i sistemi Redhat, il problema è spesso causato dalla configurazione errata di ~/.bashrcnon chiamare /etc/bashrc. Normalmente, bash carica ~/.bashrcche dovrebbe chiamare /etc/bashrc, che per impostazione predefinita contiene shopt -s checkwinsize.


Aveva lo stesso problema con OS X, apparentemente se chiami "login" per avviare il tuo terminale, inizia bash in un modo che legge / etc / bashrc, ma se chiami direttamente a bash, il ~ / .bashrc non lo fa fonte cose di default in modo da ottenere l'effetto di avvolgimento dispari. Grazie!
rogerdpack,

Questo ha funzionato anche per me. I colori non erano attivi in ​​questo particolare server, chiamavano corretti /etc/bashrc, tutto il resto andava bene ... risulta che questa è la causa dei problemi di avvolgimento.
Dhaupin,


1
Sembra una buona soluzione. Ma non funziona nella mia sessione SSH, però. Non so perché. Ho eseguito il comando shopt -s checkwinsizenella sessione ssh. Ma la confezione persiste.
Qiang Xu,

Questo era esattamente il mio problema: un utente .bashrc non stava chiamando / etc / bashrc, e quindi stava facendo un casino.
Sobrique,

9

Come menzionato in altre risposte, le sequenze non stampabili come quelle \e[0;30mdovrebbero essere racchiuse \[...\].

Inoltre (e quello che non vedo ancora menzionato) sembra che \r\ndovrebbe essere al di fuori del \[...\]caso se si dispone di un prompt multilinea. Mi ci sono voluti un po 'di tentativi ed errori per capire finalmente.


8

Una volta ho letto da qualche parte (non so più dove) quell'utilizzo \001e \002invece di \[e in \]grado di risolvere questo problema. Lo ha fatto per me.

A proposito, definire PS1 non deve apparire brutto.

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

2
La mia PS1 chiama un comando che stampa sequenze di escape causando problemi di OP. Solo questa soluzione risolve il problema per me.
RickMeasham,

7

Questo suona come un problema con i COLUMNS& LINESambiente impostazioni variabili. Quando si ridimensiona la finestra, in genere vengono impostati automaticamente da gnome-terminal (credo), è possibile forzarli a essere impostati manualmente inviando il comando resize.

Esempio

Se ridimensiono il mio terminale gnome su 79x17 le mie variabili si presentano così:

$ echo $COLUMNS; echo $LINES
79
17

Posso forzarlo in questo modo:

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

1
Interessante, ma non aiuta.
Muricula,

1
Questo risolto il mio problema non stava avvolgendo le linee correttamente dopo che ho eseguito il comando "schermo". Grazie!!
nukeguy,

5

Per evitare il wrapping, puoi anche aumentare il numero di colonne usando, ad es

stty columns 120

1
non è una buona idea, ha incasinato brutalmente Vim
phil294,

3

Inoltre, lo stesso problema può essere causato dall'utilizzo di simboli unicode ampi (come da https://stackoverflow.com/a/34812608/1657819 ). Ecco il frammento di codice che causa il problema (mente la $Greene $Redsono adeguatamente sfuggito stringhe di colore):

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 non è in grado di calcolare correttamente la lunghezza, quindi il modo più semplice potrebbe essere quello di sfuggire a 2 su tre parti di quei simboli larghi.

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

Ha senso. Quello che immagino è che bash conta i personaggi. Poiché X richiede un carattere ma è scritto come 3, è necessario racchiuderne 2 per correggere il conteggio. @blauhirn answer spiega anche come fare in una funzione con \001e \002.
Akostadinov

Cordiali saluti, questo è il modo per capire come uscita caratteri Unicode multi-byte in questo formato: stackoverflow.com/a/602924/520567
akostadinov
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.