Bash

bash:提示在視覺上被破壞

  • November 30, 2021

我的配置的想法PS1是顯示一些擴展資訊,例如 Mercurial 或 Git 儲存庫狀態、命令執行時間等。提示被分成兩行,因為它產生的字元太多而無法放入一行。這是我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

這就像包裹在第二行導致完全混亂(見中間的 $ 符號)。它幾乎適用於較大的終端列號,例如 120:

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

此外,我注意到在終端行末尾添加更多文本會導致一個問題,該問題與上述 80 列所描述的效果非常相似。問題是:是否bash錯誤地處理新行或“太長” PS1

謝謝。


更新

這個問題與我瀏覽歷史記錄時為什麼我的 bash 提示出錯?. 在與@AdamKatz 進行了一些討論之後,似乎零長度輸出轉義\[並且']僅在將它們逐字放入PS1字元串時才起作用,但是當從導致在終端上出現未轉義的函式返回時它們似乎不起作用。

對於多行提示(包括換行時,包括您的命令),您需要將顏色程式碼括在轉義的方括號中(如\[$color\])。

這個例子是綠色的,有user@hostname:workingdir $ 然後又恢復為無色:

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

如果您看到文字\[[出現在您的提示中,則它可能在被解釋為提示擴展之前已從 擴展\[到。[在這種情況下,嘗試\001for\[\002for \],您應該一切順利。如果您沒有運氣,請\e嘗試\033。這些八進制程式碼更具可移植性,因為它們會通過(程序sed不會嘗試對它們進行轉義或解釋)。

引用自:https://unix.stackexchange.com/questions/191004