bash:プロンプトが視覚的に壊れています。

bash:プロンプトが視覚的に壊れています。

私の設定のアイデアPS1は、MercurialまたはGitリポジトリの状態、コマンドの実行時間などのいくつかの拡張情報を表示することです。プロンプトは、1行に入ることができないほど多くの文字を生成するため、2行に分割されます。私が持っているものは次のとおりですPS1.bashrcここで完全なソースコードが必要かどうかはわかりません)。

function prompt_status {
        local color_app="\e[1;38;5;214m"
        local color_branch="\e[1;38;5;32m"
        local color_revision="\e[0;38;5;64m"
        if git rev-parse --is-inside-work-tree &> /dev/null; then
                local branch="$(git rev-parse --abbrev-ref HEAD | tr -d '\n')"
                local revision="$(git rev-parse HEAD | tr -d '\n')"
                echo -ne $color_app"git "$color_branch"$branch "$color_revision"($revision)"
        elif hg status &> /dev/null; then
                local branch="$(hg branch | tr -d '\n')"
                local revision_number="$(hg identify -n | tr -d '\n')"
                local revision="$(hg parent --template '{node}' | tr -d '\n')"
                echo -ne $color_app"hg "$color_branch"$branch "$color_revision"($revision_number:$revision)"
        else
                return
        fi
        echo -e " \e[0m"
}

function prompt_return_value {
        RET=$?
        if [[ $RET -eq 0 ]]; then
                echo -ne "" #echo -ne "\e[32m$RET\e[0m"
        else
                echo -ne "\e[1;37;41m$RET\e[0m "
        fi
}

function timer_start {
        timer=${timer:-$SECONDS}
}

function timer_stop {
        seconds_elapsed=$(($SECONDS - $timer))
        unset timer
}

function prompt_seconds_elapsed {
        local c;
        local t=${seconds_elapsed}s
        if [ $seconds_elapsed -ge 60 ]; then
                c=196
                t=$(format_seconds $seconds_elapsed)
        elif [ $seconds_elapsed -ge 20 ]; then
                c=214
        elif [ $seconds_elapsed -ge 10 ]; then
                c=100
        elif [ $seconds_elapsed -ge 5 ]; then
                c=34
        elif [ $seconds_elapsed -ge 1 ]; then
                c=22
        else
                return
        fi
        echo -ne "\e[0;38;5;${c}m${t} \e[0m"
}

function format_seconds {
        ((h=${1}/3600))
        ((m=(${1}%3600)/60))
        ((s=${1}%60))
        printf "%02d:%02d:%02d\n" $h $m $s
}

trap 'timer_start' DEBUG
PROMPT_COMMAND=timer_stop

export PS1="\n\e[1;38;5;106m\u@\h \e[0;38;5;136m\w\[\e[0m\]\n\$(prompt_return_value)\$(prompt_seconds_elapsed)\$(prompt_status)\$ "

問題は、端末ウィンドウの幅が小さい場合、プロンプトが壊れて見えることです。これが私が80列から得たものです:

username@some-very-long-hostname ~/tmp/d
06a14b06cac) $ 9866c9d0d26d2b27063a89ee1c330

2行目を囲むのと同じように、完全な混乱を引き起こします(中央の$記号を参照)。より大きな端末列番号(120など)の場合、ほぼ完全に機能します。

username@some-very-long-hostname ~/tmp/d
hg default (0:69866c9d0d26d2b27063a89ee1c3306a14b06cac) $

また、ターミナル行の末尾にテキストを追加すると、上記の列80で説明したものと非常によく似た効果が発生することも確認しました。問題は、bash新しい行が誤って処理されているか、「長すぎる」ことですPS1

ありがとうございます。


修正する

この質問は正確に重複した質問ではありません。履歴検索でbashプロンプトに問題が発生するのはなぜですか?。 @AdamKatzと議論した結果、長さがゼロの出力がエスケープされ、文字通り\[文字']列に入力されたときにのみ機能しているように見えますが、関数から返さPS1れたときは機能しないため、端末でエスケープされていない結果が発生します。

ベストアンサー1

複数行プロンプト(新しい行を折り返すときのコマンドプロンプトを含む)の場合は、次のものが必要です。カラーコードをエスケープされた角かっこで囲みます。(良い\[$color\])。

この例は緑色でuser@hostname:workingdir $ 、無色に戻ります。

PS1='\[\e[1;32m\]\u@\h:\w \$\[\e[0;0m\]'

テキストが表示されたり\[[プロンプトに表示された場合は、おそらくプロンプト拡張として解釈される前にから拡張されている可能性があります\[[この場合、努力し\001続ければうまくいくでしょう。運が悪い場合は、一度試してください。これらの8進コードはパスするので、移植するのは簡単です(類似したプログラムはそれをエスケープしたり解釈しようとしません)。\[\002\]\e\033sed

おすすめ記事