如何修復 color bash 提示換行問題?

如何修復 color bash 提示換行問題?

我定義了一個 bash 提示字元(使用 PROMPT_FUNCTION),如下所示:

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

一般來說,這會給我一個多行提示,顯示一些 hg 狀態資訊以及我目前的 virtualenv,看起來(沒有顏色)如下所示:

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

問題是,這擾亂了提示長度的計算(我認為!)並導致奇怪的終端換行問題和遊標放置。例如,在 80 個字元的終端機中,這是我看到的提示(** 包圍的字元是遊標位置):

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

在寬度足以顯示提示的終端機中,換行發生得比應有的早得多;這是我能容納最多的文字第一的108 個字元寬的終端視窗中的提示行(同樣,** 標記了我的遊標位置):

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

當該行換行時,它會覆蓋提示。然而,第二行輸入直接延伸到終端的邊緣,然後正確換行。

所以,顯然有些東西擾亂了提示的寬度。如何使 bash 不根據 ANSI 轉義碼,而是根據提示符的實際顯示長度來確定 PS1 字串的長度?

答案1

bash用於\[ \]確定「顯示長度」:這兩個轉義之間的文字被認為是不可列印的,並且不計入總長度;其他一切都是。

您的變數似乎有問題:bright='\[[01m\]'實際上不包含 ESC 字符,因此[01m會作為普通文字列印,但不計入長度。它應該是'\[\e[01m\]'。所有其他變數都相同。


有關的:

  • 在 Bash 中,您可以直接 put \$(hg_status)to $PS1,而不需要單獨的PROMPT_COMMAND.

相關內容