この記事はeeic (東京大学工学部電気電子・電子情報工学科)その2 Advent Calendar 2017の18日目でございます。
みなさんはシェルとして何を使っていますか?今の流行りはfishっぽいですが、移行がめんどいという理由だけでbashを使う人です。
今回は軽いbash $PS1の話をしたいと思います。
$PS1って何
bashの$PS1は特殊変数で、コマンド入力待ち状態のときに表示されるプロンプトのフォーマットを制御しています。
おもむろに
$ echo $PS1
してみましょう。(カスタマイズされていなければ) その環境でデフォルトで設定されている変数がでてくるはずです。
(ubuntu)$ echo $PS1
${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$
(centos)$ echo $PS1
[\u@\h \W]\$
(gentoo)$ echo $PS1
\[\033]0;\u@\h:\w\007\]\[\033[01;32m\]\u@\h\[\033[01;34m\] \w \$\[\033[00m\]
適当にプロンプトを変更してみましょう。
$ PS1='eeicはブラック学科である $'
ブラックというわりには文字がホワイトで表示されていますね!学科がブラックというのはやっぱり嘘でした!("電気系マフィア"1 に銃を突きつけられながら)
という学科の人にしか通じないローカルネタを挟んだところで、次に移りたいと思います。
PS1をカスタマイズしてみよう!
さっきecho $PS1
したときに、よくわからないバックスラッシュ \
が含まれていたことに気が付いた人がいるかもしれません (環境によってバックスラッシュがない場合もあります、CentOSとか) 。
このバックスラッシュには当然意味があります。いくつか挙げてみましょう。
-
\u
: 現在のユーザー名 -
\h
: ホスト名 -
\w
: 今いるディレクトリ (current working directory=作業ディレクトリ) のパス、ホームディレクトリは~
になる -
\W
: 今いるディレクトリの名前2、ホームディレクトリは~
になる -
\$
: rootならば#
、それ以外なら$
それ以外にも使われていますが、あとで述べます。
これを組み合わせればあなただけのプロンプトが完成です! (基本的にPS1を設定するときにはシングルクオーテンション'
でくくってあげましょう)
$ PS1='YUKI.N>'
YUKI.N>PS1='わたし\uさん。今\wにいるの。'
わたしmerryさん。今~にいるの。PS1='\$\$\u\u'
$$merrymerry
ちなみに、PS1の設定はそのセッションしか有効ではないので注意しましょう (ターミナルを再起動するともとに戻ります)。気に入った設定は、~/.bashrcに追記すると次回起動時にも適用されるようになります3。
色を付けよう!
さて、UbuntuとGentooマンなら、プロンプトに色がついていたことを思い出してください。もちろんついてないこともあります。あと、CentOSはデフォルトでは色がついてない気がします。
なんと、対応しているターミナルを使っていれば、色のついた文字を表示することが出来ます。試してみましょう。
$ printf '\e[31ma\e[32mb\e[33mc\e[34md\e[35me\e[36mf\e[0m\n'
abcdef ←色付きで表示される
printfに渡した引数通りに表示されていないことはわかるかと思います。
実はターミナルは、ESC文字 (ASCII 27=0x1b=033) から始まる、一定の決まりに沿った文字列 (エスケープシーケンス) を認識して、特殊な効果を付けてくれるのです。
詳しい説明は「ANSI エスケープシーケンス」あたりでググってもらうとして、色の付け方はだいたい下のような感じで付けられます (ESC文字は\e
で表しています。
文字色 | 背景色 | |
---|---|---|
黒 | \e[30m | \e[40m |
赤 | \e[31m | \e[41m |
緑 | \e[32m | \e[42m |
黄色 | \e[33m | \e[43m |
青 | \e[34m | \e[44m |
マゼンタ | \e[35m | \e[45m |
シアン | \e[36m | \e[46m |
白 | \e[37m | \e[47m |
※色は環境の設定によって異なる場合があります。
シーケンス | |
---|---|
リセット (色、太字設定をもとに戻す) | \e[0m |
太字 (色も一緒に変わることが多い) | \e[1m |
複数同時指定も可能です、たとえば\e[1;32;41m
ならば後続の文字が緑色の太字、背景が赤色になります。
さて、Ubuntuのデフォルト$PS1について解読してみましょう。debian_chrootは邪魔なので消します。あと上での\e
が\033
になっていることに注意してください。
\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$
-
\[
: 不可視文字列の始端。色を付けるためのエスケープシーケンスは表示されないので必要。 -
\033[01;32m
: エスケープシーケンス。後続の文字を太字の緑色系にする。01と1は (たぶん) 一緒の意味です -
\]
: 不可視文字列の終端。 -
\u@\h
: 上で述べたとおりなので省略します。 -
\[\033[00m\]
: 不可視文字列の始端、色・太字のリセット、不可視文字列の終端 -
:
: コロン -
\[\033[01;34m\]
: 不可視文字列の始端、後続の文字を太字の青色系にする、不可視文字列の終端 -
\w
: 上の章で述べた、今のディレクトリパス -
\[\033[00m\]\$
: 省略
和訳してあげると、ユーザー名@ホスト名
を緑色系で表示、:
をデフォルトの色で表示、作業ディレクトリ
を太字の青色系で表示、$と空白 (rootなら#と空白)
をデフォルトの色で表示。となります。実際に確認してみましょう。
和訳した通りみたいですね!
もっとPS1で遊ぶ
\w
でディレクトリパスを表示すると、深いディレクトリ階層のときに表示が長くなりすぎるってことありますよね。
それが嫌で\W
を設定する人もいるとおもいますが、最後のパスだけ表示されてもどこにいるかわからないってのも困ったりしませんか?
そういう方にはこのgistのsmart_pwdが役に立つと思います。
function smart_pwd {
local pwdmaxlen=25
local trunc_symbol=".."
local dir=${PWD##*/}
local tmp=""
pwdmaxlen=$(( ( pwdmaxlen < ${#dir} ) ? ${#dir} : pwdmaxlen ))
NEW_PWD=${PWD/#$HOME/\~}
local pwdoffset=$(( ${#NEW_PWD} - pwdmaxlen ))
if [ ${pwdoffset} -gt "0" ]
then
tmp=${NEW_PWD:$pwdoffset:$pwdmaxlen}
tmp=${trunc_symbol}/${tmp#*/}
if [ "${#tmp}" -lt "${#NEW_PWD}" ]; then
NEW_PWD=$tmp
fi
fi
}
PROMPT_COMMAND="smart_pwd"
PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]${NEW_PWD}\[\033[00m\]\$ \$'
ちょっと長いですが、これを.bashrcに書いてあげると、
のように、長いパスもいい感じに短くなります。ぼくは先頭一文字 (?) が表示されるタイプ (~/t/o/m/c/s/o/r/g/filter) より、目一杯表示できる分だけパスを表示してくれる方が好きです。
256色なプロンプトを使ってみる
実はターミナルによっては、エスケープシーケンスを応用することで256色を表示することが出来る場合があります (Linuxのgnome-terminalは対応しています)。
文字色は\e[38;5;<色番号>m
、背景色は\e[48;5;<色番号>m
で設定できます。256色がどのような色かはxterm-colortest.plなどを使えば見ることが出来ます。
256色もあればきっと他の人と被らない、オリジナルプロンプトを作ることも容易いことでしょう。
最後に自分の$PS1晒し
母艦はだいたいこんな感じの設定を使っています。dotfiles
\[\e[$[COLUMNS-19]C\]\[\033[48;5;55m\033[38;5;220m\D{%a %b %d %T}\r\033[0m\]\[\033[48;5;17m\033[38;5;117m\]\u\[\033[38;5;114m\]@\[\033[38;5;117m\]\h \[\033[48;5;232m\033[38;5;201m\]${SMART_PWD_TRUNC}\[\033[38;5;86m\]${SMART_PWD}\[\033[0m\]\n\[\033[38;5;41m\]$(__git_ps1 "(%s)")\[\033[38;5;208m\]\$\[\033[0m\]
function smart_pwd {
local pwdmaxlen=$(( $COLUMNS-35 ))
local trunc_symbol=".."
local dir=${PWD##*/}
local tmp=""
pwdmaxlen=$(( ( pwdmaxlen < ${#dir} ) ? ${#dir} : pwdmaxlen ))
if [[ $PWD == $HOME* ]]; then
SMART_PWD="~${PWD#${HOME}}"
else
SMART_PWD="$PWD"
fi
# set title
printf "\033]0;%s\007" "${USER}@${HOSTNAME}: ${SMART_PWD}"
SMART_PWD_TRUNC=""
local pwdoffset=$(( ${#SMART_PWD} - pwdmaxlen ))
if [ ${pwdoffset} -gt "0" ]
then
tmp=${SMART_PWD:$pwdoffset:$pwdmaxlen}
tmp=${trunc_symbol}/${tmp#*/}
if [ "${#tmp}" -lt "${#SMART_PWD}" ]; then
SMART_PWD_TRUNC="${trunc_symbol}"
SMART_PWD="${tmp:${#trunc_symbol}}"
fi
fi
}
# git-prompt.shの中に__git_ps1があるので、インクルードする
# ファイルパスは環境によって違う可能性あり。https://github.com/git/git/blob/master/contrib/completion/git-prompt.sh をダウンロードでもよい
source /usr/share/git/git-prompt.sh
PROMPT_COMMAND="smart_pwd"
PS1='\[\e[$[COLUMNS-19]C\]\[\033[48;5;55m\033[38;5;220m\D{%a %b %d %T}\r\033[0m\]\[\033[48;5;17m\033[38;5;117m\]\u\[\033[38;5;114m\]@\[\033[38;5;117m\]\h \[\033[48;5;232m\033[38;5;201m\]${SMART_PWD_TRUNC}\[\033[38;5;86m\]${SMART_PWD}\[\033[0m\]\n\[\033[38;5;41m\]$(__git_ps1 "(%s)")\[\033[38;5;208m\]\$\[\033[0m\]'
これを設定するとだいたいこんな感じになります
まあこんなかんじで、256色、日時、いい感じのパス表示、gitの情報表示、などが組み合わさった、個人的に気に入っている設定になります。
みなさんもいい感じのPS1をつくってみてね!