カラーbashプロンプトの折り返しを修正するにはどうすればよいですか?


9

私は次のように(PROMPT_FUNCTIONを使用して)bashプロンプトを定義しました:

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

行が折り返されると、プロンプトが上書きされます。ただし、入力の2行目はターミナルの端まで実行され、正しく折り返されます。

ですから、プロンプトの幅で何かが混乱しているのは明らかです。ANSIエスケープコードではなく、実際に表示されるプロンプトの長さに基づいて、PS1文字列の長さをbashに決定させるにはどうすればよいですか?

回答:


21

bash\[ \]「表示される長さ」を決定するために使用します。これら2つのエスケープの間のテキストは印刷できないと見なされ、全長には含まれません。他はすべてです。

変数に問題があるようです。bright='\[[01m\]'実際にはESC文字が含まれていないため[01m、通常のテキストとして印刷されますが、長さにはカウントされません。それはする必要があります'\[\e[01m\]'。他のすべての変数についても同じです。


関連:

  • Bashでは、別のを必要とせず\$(hg_status)$PS1直接配置できますPROMPT_COMMAND

1
これは部分的な修正を提供します。行の長さが正しく検出されるようになりましたが、最初の行の折り返しがプロンプトに上書きされるという問題は修正されません。
Chris R

1
クリスR:私はあなたのプロンプトを試して、すべて'\[['\[\e[Ubuntu 12.04のbashで動作するものに置き換えました。エスケープカラー(およびその他の\[...\]重要ではないサイズのパーツ)も役に立ちましたが、私はあなたよりもはるかに複雑なPS1を持っています(右揃えのテキストがプロンプトと同じ行にあり、右下のテキストがテキストです)コーナー)。初期のラッピングと重複するラッピングの問題の両方が修正されました。
TWiStErRob
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.