まさはる's Weblog

まさはる's Weblog
Macintoshとオーディオの話題

2002年12月21日

Bashのプロンプト

Category : Terminal / Posted at 2002年12月21日 00:00

 Bash Prompt HOWTOにBashのプロンプトについて詳しい説明があるので、それを参考にプロンプト幅が一定になるように改良してみました。

CLUMNS幅のプロンプト
プロンプト幅がターミナルのカラム幅と同じになるようにプロンプトを設定

 また、システムの負荷値*1を表示して、その状態により色を変えるようにしてみました。上の図では左から、[ヒストリ番号][ユーザ名@ホスト名(負荷値)]---[カレントディレクトリ名]を表示しており、.bashrcのPS1の設定を以下のサンプルにすると、上記のようになります。

● サンプルの.bashrc(該当部分のみ)

# ********************
# CLUMNS幅のプロンプト
# ********************
function prompt_command {
    # 文字列、数値の取得
    # HOSTNAMEの.以下を削除
    strHostname=$(echo -n $HOSTNAME | sed -e "s/\..*\.//")
    # PWDのHOME以下を~に変更
    strPwd=$(echo -n $PWD | sed -e "s:^$HOME:~:")
    # システムの1分間の平均負荷の数値を抽出
    valHostLoad=$(uptime | sed -e "s/.*load averages: \(.*\...\), \(.*\...\), \(.*\...\)/\1/" -e "s/ //g")
 
    # プロンプトをCOLUMNS幅に調整
    # [xxx][user@hostname(x.xx)]---[~]$
    # Prompt全体の長さを取得
    local valPromptSize=$(echo -n "[$HISTCMD][$USER@$strHostname($valHostLoad)][$strPwd]" | wc -c | tr -d " ")
    # COLUMNSに値が入っていない場合は80を初期値とする
    local valFillSize=$(( ${COLUMNS:-80}-$valPromptSize ))
    strFill=""
    # 短い場合は$strFillに"-"を追加
    while [ $valFillSize -gt 0 ]
    do
        strFill="-$strFill"
        valFillSize=$(( $valFillSize-1 ))
    done
    # 長い場合は$strPwdの左側を"..."に置き換えて削除
    if [ $valFillSize -lt 0 ]
    then
        local valCutSize=$(( 3-$valFillSize ))
        strPwd="...$(echo -n $strPwd | sed -e "s/\(^.\{$valCutSize\}\)\(.*\)/\2/")"
    fi
 
    # システムの1分間の平均負荷に応じてカラー設定
    # bcは乗算すると小数点が入るので除算する
    local valHostLoadInt=$(echo -e "$valHostLoad/0.01\nquit\n" | bc)
    # ANSI Escape Sequences
    # 0:normal 1:bold 4:underline 5:blink 7:reverse video 8:nondisplayed
    # 30-37,39:foreground Color 39:default
    # 30:black 31:red 32:green 33:yellow 34:blue 35:magenta 36:cyan 37:white
    # 40-47,49:background Color 49:default
    # 40:black 41:red 42:green 43:yellow 44:blue 45:magenta 46:cyan 47:white
    if [ $valHostLoadInt -ge 200 ]
    then
        strHostLoadColor=31     # red
    else
        if [ $valHostLoadInt -ge 100 ]
        then
            strHostLoadColor=35 # magenta
        else
            strHostLoadColor=0  # normal
        fi
    fi
}
PROMPT_COMMAND=prompt_command
PS1='\n[$HISTCMD][$USER@$strHostname(\[\e[${strHostLoadColor}m\]$valHostLoad\[\e[0m\])]$strFill[$strPwd]\$ '

 なお、既知の問題点として、パス名に日本語を含んでいるとズレ*2てきます。

*1 負荷値はuptimeの1分間の平均値を使っていて、これは待ちスレッドの数だそうです。私が普通に使っていると1以下なので、1を超えると色の変更をするようにしていますが、使用環境によっては2ぐらいが適当かもしれません。
*2 wcで文字数を数えているのですが、日本語(utf-8)はどうやら1文字が3バイトあるため、英数2文字分の幅を3文字とカウントしてしまうところに問題がありそうです。

 上記の場合、Mac OS X v10.3では正しく表示されません。変数やコマンドの出力が変更になっているようです。

● $HOSTNAME
 10.2の場合は"コンピュータ名.local."というふうに、最後に"."が付いていたのですが、10.3では付かなくなりました。したがって、コンピュータ名をsedで抜き出している箇所でエラーになります。

strHostname=$(echo -n $HOSTNAME | sed -e "s/\..*\.//")
      ↓
strHostname=$(echo -n $HOSTNAME | sed -e "s/\..*//")

● uptime
 10.2のuptimeは、負荷の値がコンマ+空白区切りだったのですが、10.3ではコンマが無くなり空白のみになりました。これも、1分間の平均負荷をsedで抜き出している箇所でエラーになります。

valHostLoad=$(uptime | sed -e "s/.*load averages: \(.*\...\), \(.*\...\), \(.*\...\)/\1/" -e "s/ //g")
      ↓
valHostLoad=$(uptime | sed -e "s/.*load averages: \(.*\...\) \(.*\...\) \(.*\...\)/\1/" -e "s/ //g")

● エスケープシーケンス
 これは原因がよく分からないのですが、プロンプトがズレて表示されてしまいます。とりあえずエスケープシーケンスの部分を削除して使っています。

PS1='\n[$HISTCMD][$USER@$strHostname(\[\e[${strHostLoadColor}m\]$valHostLoad\[\e[0m\])]$strFill[$strPwd]\$ '
      ↓
PS1='\n[$HISTCMD][$USER@$strHostname($valHostLoad)]$strFill[$strPwd]\$ '

(2003.12.14追記)
 上記エスケープシーケンスでズレて表示される問題は、最初の \n を取り除くことで解決しました。でもなぜ...(^_^;

このページのトップに戻る