ターミナルのタブを複数開けて作業するときに設定して便利だったこと

　ターミナルのタブを複数開けて、異なるプロジェクトを同時並行で作業することがあった。それで主に下記の2点が不便だったので、なんとかできんかなーと思い色々やってみた。

# 解決したい課題
- ターミナル / IDE / エディタ等を行き来すると、どのタブがどのプロジェクトを開いているのか、パッと見てすぐに分からないので、すぐに分かるようにしたい
- それぞれのタブで打ったコマンドの履歴が独立していて、`↑`ボタンで思ったコマンドがでないのでなんとかしたい


# 1. 任意のディレクトでプロンプトの色を変更する
- `PROMPT_COMMAND`というシェル変数があり、この値に設定したコマンドや関数はプロンプトの表示前に実行される
- このシェル変数で、任意のディレクトに移動後、プロンプトの色を変更して、どのプロジェクトを開いてるのか色で分かるようにする
- 次の`prompt_command_color`は特定のディレクトリに移動すると、プロンプトに表示するGitのブランチ名だけ色を変更する関数です

```bash:.bash_profie

# Gitのbranchを表示
source /usr/local/etc/bash_completion.d/git-prompt.sh
source /usr/local/etc/bash_completion.d/git-completion.bash
GIT_PS1_SHOWDIRTYSTATE=true
GIT_PS1_SHOWSTASHSTATE=true
GIT_PS1_SHOWUPSTREAM=auto

# Gitのブランチ名を色付きで表示
function prompt_command_color () {
    CURRENT=$(basename `pwd`)
    if [ "$CURRENT" = 'directory1' ]; then
        export PS1='\[\e[0;36m\][\u@\h \W]\$\[\e[0m\]\[\033[01;33m\]$(__git_ps1 [%s])\[\033[00m\]\$ '
    elif [ "$CURRENT" = 'directory2' ]; then
        export PS1='\[\e[0;36m\][\u@\h \W]\$\[\e[0m\]\[\033[01;38m\]$(__git_ps1 [%s])\[\033[00m\]\$ '   
    else
        export PS1='\[\e[0;36m\][\u@\h \W]\$\[\e[0m\]\[\033[01;32m\]$(__git_ps1 [%s])\[\033[00m\]\$ '
    fi  
}

PROMPT_COMMAND=prompt_command_color

```

# 2. コマンド履歴の共有
- 下記の記事が参考になった  
http://iandeth.dyndns.org/mt/ian/archives/000651.html 

```bash:.bash_profie

# コマンド履歴の共有
function prompt_command_sync_history () {
    history -a # .bash_historyに前回コマンドを1行追記
    history -c # 端末ローカルの履歴を一旦消去
    history -r # .bash_historyから履歴を読み込み直す
}
shopt -s histappend    # .bash_history追記モードは不要なのでOFFに
HISTCONTROL=ignoreboth # コマンドの重複を防ぐ

PROMPT_COMMAND=prompt_command_sync_history

```

# 1. と2. の関数を `PROMPT_COMMAND` ヘ同時に設定する

　一つの関数でまとめてやればすぐにできる。でも、機能追加するたびに行が長くなるし、同じ関数で別々の処理が走るので辛い。

　処理ごとに関数を分けて `PROMPT_COMMAND` に設定したい。でも、複数の関数を一つのシェル変数に設定する方法が分からずハマる。

- 下記の記事で出来た助かった  
http://qiita.com/tay07212/items/9509aef6dc3bffa7dd0c

```bash:.bash_profie

# 色を変更する関数と、履歴共有の関数をグローバルな変数に入れる
PROMPT_COMMAND_COLOR=prompt_command_color
PROMPT_COMMAND_SYNC_HISTORY=prompt_command_sync_history

# PROMPT_COMMANDに複数の関数を割り当てる関数
function dispatch () {
    for f in ${!PROMPT_COMMAND_*}; do   # ${!HOGE*}は、HOGEで始まる変数の一覧を得る
        eval ${!f}                      # ${!f}は、$fに格納された文字列を名前とする変数を参照する（間接参照・間接展開）
    done
}

PROMPT_COMMAND=dispatch

```

# こんな感じになる

- `PROMPT_COMMAND` はプロンプトの表示前に実行されるので enter 押せば、コマンド履歴は共有される

![GIF](http://i.giphy.com/26BRA4HU4LNIglj0s.gif)


# 番外編１ ： ${!f} がよくわからん
- 間接参照とか間接展開とか呼ばれてるぽい  
http://kodama.fubuki.info/wiki/wiki.cgi/bash/tips?lang=jp

```bash:例１
$ A=BBB
$ BBB=1
$ echo ${A}
BBB
$ echo ${!A} # これは eval echo \$$A や eval echo '$'$A と 同じ
1
```

# 番外編２ ： eval echo \$$A や eval echo '$'$A と 同じ？
- 同じだった  
[入門UNIXシェルプログラミング―シェルの基礎から学ぶUNIXの世界](https://www.amazon.co.jp/%E5%85%A5%E9%96%80UNIX%E3%82%B7%E3%82%A7%E3%83%AB%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E2%80%95%E3%82%B7%E3%82%A7%E3%83%AB%E3%81%AE%E5%9F%BA%E7%A4%8E%E3%81%8B%E3%82%89%E5%AD%A6%E3%81%B6UNIX%E3%81%AE%E4%B8%96%E7%95%8C-%E3%83%96%E3%83%AB%E3%83%BC%E3%82%B9%E3%83%BB%E3%83%96%E3%83%AA%E3%83%B3/dp/4797321946)

```bash:例２
$ A=BBB
$ BBB=1
$ echo $A
BBB
$ echo \$A
$A
$ echo $$A # $$はプロセスID（51856）
51856A
$ echo \$$A
$BBB
$ eval echo \$$A
1
$ eval echo '$'$A
1
```

- 要するに、 上記で自作した `dispatch` という関数で実行している `eval ${!f}` は、**fの中にある文字列**を**変数として展開**すると、中身が関数だったので、その関数をevalが実行するということだった。
 

# まとめ
- いろいろ画面を行き来しても、色でパッと見分けられ、コマンドも共有でき、快適になりました
- bashは理解するのが大変だったけど、なんか妙に引き込まれる魅力がある
- bash力が少し上がった