Bash
bash:提示在視覺上被破壞
我的配置的想法
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\]'
如果您看到文字
\[
或[
出現在您的提示中,則它可能在被解釋為提示擴展之前已從 擴展\[
到。[
在這種情況下,嘗試\001
for\[
和\002
for\]
,您應該一切順利。如果您沒有運氣,請\e
嘗試\033
。這些八進制程式碼更具可移植性,因為它們會通過(程序sed
不會嘗試對它們進行轉義或解釋)。