ターミナルカラー化で視覚的な事故防止に+α

デスクトップにターミナルを複数並べて作業することは、よくあると思う。
同じホストだけでなく、複数のホスト環境に同時アクセスしながら作業することも、実際ある話だろう。

ターミナルを並べて作業していると、ふとゲシュタルト崩壊のような状況になる。`ホストAだと思って作業していたら実はホストBだった...`、とか、`開発環境だと思ってrmしようとしたら商用環境だった...`、なんて、ヒヤリハットな体験は、本当に肝を冷やす。。。
こういうヒューマンエラーを無くす１つの方法として、小生の場合は、視覚的にどのホストなのかをぱっと見の色で区別するようにしている。

さて、シェルのプロンプトの色付けをしてみよう。

## 目的

- ホスト間違い（確認ミス）などによるヒューマンエラーの低減策の１つ。
- 少し汎用的に、そして（シェル特有の書式から離れて）簡便に使いたい。
- もちろん、これで全て解決できるわけではないので、他の予防策とあわせて行おう。

## 要件

- `/etc/profile.d`の下に`prompt.sh` を作成。
    - BASHユーザー対象。BASH以外のユーザーは、それぞれのシェルにあわせて改変を。
- シェルコマンド `tput` に依存している。
    - なのでターミナル依存になるかもしれない。（よく調べていない）
    - 当方の作業環境のLinux(Amazon Linux, CentOS)およびMac環境では動作確認済み。

## 実装

```bash:/etc/profile.d/prompt.sh
# Prompt colorizer

# font()
# Set escape sequances to given parameter
font(){
    local PARAM=$1
    local ATTR='' S OP
    shift

    for OP in $*
    do
        case $OP in
            [0-9]|[0-9][0-9]|[1-2][0-9][0-9])           # 'NNN'   ... foreground color
                S="\[$(tput setaf $1)\]" ;;
            bg[0-9]|bg[0-9][0-9]|bg[1-2][0-9][0-9])     # 'bgNNN' ... background color
                S="\[$(tput setab $(echo $1 | sed 's/bg//'))\]" ;;
            [bB] ) S="\[$(tput bold)\]"  ;;             # b|B     ... Bold
            [fF] ) S="\[$(tput dim)\]"   ;;             # d|D     ... Faint
            [lL] ) S="\[$(tput blink)\]" ;;             # l|L     ... Blink
            [uU] ) S="\[$(tput smul)\]"  ;;             # u|U     ... Underlined
            * ) S=$1 ;;
        esac
        shift
        ATTR="$ATTR$S"
    done
    ATTR="$ATTR\[$(tput sgr0)\]"
    eval $PARAM="\"$ATTR\""
}

# --- Color# aliases ---
_BLK0=0;   _BLK1=8
_RED0=1;   _RED1=9
_GRN0=2;   _GRN1=10
_YLW0=3;   _YLW1=11
_BLU0=4;   _BLU1=12
_MAG0=5;   _MAG1=13
_CYN0=6;   _CYN1=14
_WHT0=7;   _WHT1=15


# --- setting PSx ---
set_ps1(){
  local LABEL; font LABEL 'b' $_BLU1 devel-aws
  local SNAME; font SNAME $_CYN0 APP
  local UNAME; font UNAME 'b' $_WHT0 '\u'
  local HNAME; font HNAME $_WHT1 '\h'
  local ENAME1; font ENAME1 'f' $_WHT0 "bg21" 'GA'
  local ENAME2; font ENAME2 'f' $_WHT0 "bg34" 'ME'
  local ENAME3; font ENAME3 'f' $_WHT0 'Perfume'
  local WHERE; font WHERE $_YLW0 '\w'

  PS1="($LABEL $SNAME) $UNAME@$HNAME <$ENAME1$ENAME2$ENAME3> $WHERE\n$ " 
}

set_ps1_root(){
  # root で操作の場合は、もっと目立つように
  local LABEL; font LABEL 'b' 'u' $_BLU1 devel-aws
  local SNAME; font SNAME $_CYN0 APP
  local UNAME; font UNAME 163 '\u'
  local HNAME; font HNAME 'b' 197 '\h'
  local ENAME1; font ENAME1 'f' $_WHT0 "bg21" 'Ga'
  local ENAME2; font ENAME2 'f' $_WHT0 "bg34" 'me'
  local ENAME3; font ENAME3 'f' $_WHT0 'PERFUME'
  local WHERE; font WHERE $_RED0 '\w'
  local ATMRK; font ATMRK 'b' 'l' $_RED0 '@'
  local PRMRK; font PRMRK 218 '#'

  PS1="($LABEL) $UNAME$ATMRK$HNAME <$ENAME1$ENAME2$ENAME3> $WHERE\n$PRMRK " 
}

if [ ${EUID:-${UID}} = 0 ]; then
    # When root user
    set_ps1_root
else
    # Common accounts
    set_ps1
fi


# --- unset local parameters and subroutines ---
unset -v _BLK0 _RED0 _GRN0 _YLW0 _BLU0 _MAG0 _CYN0 _WHT0
unset -v _BLK1 _RED1 _GRN1 _YLW1 _BLU1 _MAG1 _CYN1 _WHT1
unset -f font
unset -f set_ps1
```

設定のキモは、 `set_ps1()` `set_ps1_root()` のところで呼ばれている、シェルスクリプト関数 `font` を使うところ。
`font` に修飾属性を可変長引数で渡し、引数の最後の文字列に、それら属性が順番に適用されるようにしている。イメージ的にはHTMLのタグのような感じかな。
実際どんな修飾ができるかは、ソースを見てもらったほうが早いと思う。（Faintはよく分からない、手元のターミナルでは変化が無いので）


## 問題

- 現在わかっている問題では、`ssh`で対象ホストにコマンドをつけて実行すると、警告が出る。調査後対処予定。