Come posso correggere il wrapping del prompt dei colori bash?


9

Ho definito un prompt di bash (usando PROMPT_FUNCTION) in questo modo:

function get_hg_prompt_prefix() {
    local APPLIED_COLOR=$1; shift
    local UNAPPLIED_COLOR=$1; shift
    local ALERT_COLOUR=$1; shift
    local TEXTCOLOR=$1; shift
    local mercurial_prompt_line="{{patches|join(:)|pre_applied(${APPLIED_COLOR})|post_applied(${TEXTCOLOR})|pre_unapplied(${UNAPPLIED_COLOR})|post_unapplied(${TEXTCOLOR})}\n\r}"
    local mercurial_status_prompt="{ ${ALERT_COLOUR}{status}${TEXTCOLOR}}"

    echo "$(hg prompt "${mercurial_prompt_line}" 2>/dev/null)$(hg prompt "${mercurial_status_prompt}" 2>/dev/null)"
}

function set_prompt() {
    bright='\[[01m\]'
    colors_reset='\[[00m\]'
    HOSTCOLOR=${colors_reset}='\[[34m\]'
    USERCOLOR=${colors_reset}='\[[01m\]'
    TEXTCOLOR=${colors_reset}='\[[32m\]'
    APPLIED_COLOR=${colors_reset}='\[[32m\]'
    UNAPPLIED_COLOR=${colors_reset}='\[[37m\]'
    ALERT_COLOUR=${colors_reset}='\[[31m\]'

    hg_status="$(get_hg_prompt_prefix $APPLIED_COLOR $UNAPPLIED_COLOR $ALERT_COLOUR $TEXTCOLOR)"
    ps1_prefix="${hg_status}$colors_reset($bright$(basename $VIRTUAL_ENV)$colors_reset) "
    PROMPTEND='$'
    PS1="${ps1_prefix}${USERCOLOR}\u${colors_reset}${TEXTCOLOR}@${colors_reset}${HOSTCOLOR}\h${colors_reset}${TEXTCOLOR} (\W) ${PROMPTEND}${colors_reset} "
}

PROMPT_COMMAND=set_prompt

In generale, questo mi dà un prompt multi-linea che mostra alcune informazioni sullo stato di hg e il mio virtualenv attuale, cercando (senza colore) in questo modo:

buggy-wins.patch
 ! (saas) user@computer (~) $ 

Il problema è che questo si sta rovinando con il calcolo della lunghezza del prompt (credo!) E causando strani problemi di avvolgimento dei terminali e posizionamento del cursore. Ad esempio, in un terminale a 80 caratteri, ecco il prompt che vedo (il carattere ** - circondato è la posizione del cursore):

~) $ **a**nis) crose@chris-rose (~

Nei terminali abbastanza larghi da visualizzare il prompt, il ritorno a capo avviene molto prima di quanto dovrebbe; ecco la maggior parte del testo che posso inserire nella prima riga del prompt in una finestra terminale di 108 caratteri (di nuovo, il ** segna la posizione del mio cursore):

 **(**advanis) crose@chris-rose (~) $ sdkfjlskdjflksdjff

Quando la riga termina, sovrascrive il prompt. La seconda linea di input corre tuttavia fino al bordo del terminale, quindi si avvolge correttamente.

Quindi, chiaramente qualcosa sta rovinando la larghezza del prompt. Come posso fare bash per determinare la lunghezza della stringa PS1 non in base ai codici di escape ANSI, ma in base alla lunghezza effettiva visualizzata del prompt?

Risposte:


21

bashusa \[ \]per determinare la "lunghezza visualizzata": il testo tra queste due fughe è considerato non stampabile e non viene conteggiato nella lunghezza totale; tutto il resto è.

Sembra che ci sia un problema con le tue variabili: in bright='\[[01m\]'realtà non include un carattere ESC, quindi [01mviene stampato come testo normale ma non viene conteggiato nella lunghezza. Dovrebbe essere '\[\e[01m\]'. Lo stesso per tutte le altre variabili.


Relazionato:

  • in Bash, si può mettere \$(hg_status)a $PS1direttamente, senza la necessità di un separato PROMPT_COMMAND.

1
Ciò fornisce una correzione parziale; la lunghezza della linea viene rilevata correttamente ora, ma non risolve il problema con la prima riga che sovrasta scrivendo sul prompt.
Chris R,

1
Chris R: Ho provato il tuo prompt e ho appena sostituito tutto '\[[con '\[\e[lavorato in bash su Ubuntu 12.04. Anche l'escape dei colori (e alcune altre parti irrilevanti per le dimensioni del prompt) \[...\]mi ha aiutato, ma ho PS1 molto più complessa di te (con il testo allineato a destra sulla stessa riga del prompt e il testo in basso a destra angolo). Risolveva sia i problemi di avvolgimento precoce che di sovrapposizione.
TWiStErRob
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.