Wie behebe ich meine Farb-Bash-Eingabeaufforderung?

9

Ich habe eine Bash-Eingabeaufforderung (mit PROMPT_FUNCTION) wie folgt definiert:

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

Im Allgemeinen erhalte ich dadurch eine mehrzeilige Eingabeaufforderung, die einige Informationen zum HG-Status sowie meine aktuelle virtuelle Umgebung anzeigt und (ohne Farbe) folgendermaßen aussieht:

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

Das Problem ist, dass dies mit der Berechnung der Länge der Eingabeaufforderung (glaube ich!) Verschraubt wird und seltsame Probleme beim Umschließen des Terminals und bei der Platzierung des Cursors verursacht. In einem 80-Zeichen-Terminal wird beispielsweise die Eingabeaufforderung angezeigt (das ** - umgebene Zeichen ist die Cursorposition):

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

In Terminals, die breit genug sind, um die Eingabeaufforderung anzuzeigen, erfolgt der Zeilenumbruch viel früher als erwartet. Hier ist der meiste Text, den ich in die erste Zeile der Eingabeaufforderung in einem 108 Zeichen breiten Terminalfenster einfügen kann (wieder markiert das ** meine Cursorposition):

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

Wenn die Zeile umbrochen wird, wird die Eingabeaufforderung überschrieben. Die zweite Eingabezeile verläuft jedoch bis zum Rand des Terminals und wird dann korrekt umbrochen.

Es ist also klar, dass etwas mit der Breite der Eingabeaufforderung zu tun hat. Wie kann ich veranlassen, dass bash die Länge der PS1-Zeichenfolge nicht anhand der ANSI-Escape-Codes, sondern anhand der tatsächlich angezeigten Länge der Eingabeaufforderung ermittelt?

Chris R.
quelle

Antworten:

21

bashwird \[ \]zur Bestimmung der "angezeigten Länge" verwendet: Text zwischen diesen beiden Escapezeichen wird als nicht druckbar betrachtet und nicht in die Gesamtlänge einbezogen. alles andere ist.

Es scheint ein Problem mit Ihren Variablen zu geben: bright='\[[01m\]'Enthält kein ESC-Zeichen, wird also [01mals normaler Text gedruckt, aber nicht in der Länge gezählt. Es sollte sein '\[\e[01m\]'. Gleiches gilt für alle anderen Variablen.


Verbunden:

  • in Bash, können Sie setzen , \$(hg_status)um $PS1direkt, ohne die Notwendigkeit eines separaten PROMPT_COMMAND.
user1686
quelle
1
Das bietet eine teilweise Lösung; Die Zeilenlänge wird jetzt korrekt erkannt, aber das Problem mit dem ersten Zeilenumbruch, der über die Eingabeaufforderung geschrieben wird, wird nicht behoben.
Chris R
1
Chris R: Ich habe Ihre Eingabeaufforderung ausprobiert und nur alle '\[[durch '\[\e[in Ubuntu 12.04 funktionierende Bash ersetzt. Es \[...\]hat mir auch geholfen, Farben (und einige andere Teile, die für die Größe der Eingabeaufforderung irrelevant sind) zu entkommen, aber ich habe eine viel, viel komplexere PS1 als Sie (mit rechtsbündigem Text in derselben Zeile wie Eingabeaufforderung und Text unten rechts) Ecke). Es wurden sowohl die frühen als auch die überlappenden Verpackungsprobleme behoben.
TWiStErRob