LoginSignup
6
8

More than 5 years have passed since last update.

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

Last updated at Posted at 2016-08-10

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

解決したい課題

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

1. 任意のディレクトでプロンプトの色を変更する

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

.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 に設定したい。でも、複数の関数を一つのシェル変数に設定する方法が分からずハマる。

.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

番外編1 : ${!f} がよくわからん

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

番外編2 : eval echo \$$A や eval echo '$'$A と 同じ?

例2
$ 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力が少し上がった
6
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
8