【コラム】

漢のzsh

2 取りあえず、プロンプトを整えておく。カッコつけたいからね

2/24

補完の深みに入るまえに、今回は基本の設定をしてしまおう。設定は~/.zshrcファイルに書き込んで、source ~/.zshrcで反映だ。zshに直接入力して設定を有効にさせてみてもいいが、~/.zshrcに書き込まないと、次に起動したときzshはきれいさっぱり忘れているので気をつけるように。

環境変数LANG

まずは、環境変数LANGを設定しよう。zshから実行するコマンドやアプリケーションがLANGで指定したロケールで動作するようになる。最近のOSなら設定はリスト1.1のようにUTF-8を設定すればいい。Linux/FreeBSDで古いディスとリビーションやバージョンを使っている場合、もしくは、LaTeXなどUTF-8へ対応していないアプリケーションを使う場合はリスト1.2のようにEUC-JPを設定しておけばいいだろう。

リスト1.1 環境変数LANGをja_JP.UTF-8へ設定 - Linux/FreeBSD/Mac OS X

export LANG=ja_JP.UTF-8

リスト1.2 環境変数LANGをja_JP.eucJPへ設定 - Linux/FreeBSD - LaTeXなどEUC-JPを要求するアプリを使う場合など

export LANG=ja_JP.eucJP

なんでログインシェルでLANGを設定するかだが、これには理由がある。シェルから起動されるコマンドやアプリケーションにはシェルで設定された環境変数が引き継がれる。だからログインシェルの設定ファイルでLANGを設定するわけだ。

プロンプト

プロンプトは、まさにシェルの「顔」。最も好みがでる設定のひとつだ。漢としては、カッコつけるためにもこだわりたい。

zshには、プロンプトでカッコつけるための強力な設定がある。せっかくなので設定して御利益をうけておこう。というか、プロンプトを同じにしておくと、シェルを変えてもだれも気付いてくれないし……

設定には、シェル変数PROMPT/PROMPT2/PROMPT3/PROMPT4/SPROMPTが利用できる(ほかのシェルと同じ名前のprompt、PS1、PS2、PS3、PS4も用意されているが、動作は一緒だ)。

変数の意味についてはここここあたりをご覧いただくとして、少なくともPROMPT、PROMPT2、SPROMPTあたりを設定しておけばいいだろう。リスト2.1あたりが基本的といったところだ。

リスト2.1 プロンプトの設定例 - PROMPT、PROMPT2、SPROMPTあたりは設定しておこう

PROMPT="%/%% "
PROMPT2="%_%% "
SPROMPT="%r is correct? [n,y,a,e]: "

PROMPTは通常のプロンプト、PROMPT2はforやwhile/複数行入力時などに表示されるプロンプト、SPROMPTは入力ミスを確認する場合に表示されるプロンプトだ。

図2.2 プロンプトにカレントディレクトリを表示させている

図2.3 複数行の入力や制御構文入力の場合に構文名がプロンプトに表示されている

図2.4 コマンド入力ミスを確認する場合のプロンプト

PROMPT、PROMPT2、SPROMPTで使われている「%/」や「%_」、「%%」がそれぞれ意味のある値になっている。ここあたりにそれぞれ説明があるので参考にしてほしい。結構変態的なプロンプトも設定できるので、プロンプトを設定しながら悶絶してみるのもいいだろう。

ちなみに筆者が使っているプロンプト設定はリスト2.5。一般ユーザとrootで表示されるプロンプトの色合いが変わる。

あと、ローカルでの作業とsshでリモートログインして作業する場合も色合いが変わる。うっかりリモートをローカルと勘違いして設定変更とかファイルを削除とか、お取引先を困らせたりしがち、というかしたことがあるので、それを防止するためだ。自分のマシンだと思って隣りの人のマシンの設定を書換えながら、お互い頭を抱えたこともある。まさに時間の無駄である。

ちなみに、ホストごとに出る色を変えるようにするかと考えたこともあるが、見にくいホストとかが出てきがちだし、そもそもホストと色の対応も覚えられない。実際問題使い物にならないね、ということで、これはやめた。

リスト2.5 プロンプトの設定例 - 応用例 - 状況によってプロンプトを変えている。色もつく

case ${UID} in
0)
    PROMPT="%B%{^[[31m%}%/#%{^[[m%}%b "
    PROMPT2="%B%{^[[31m%}%_#%{^[[m%}%b "
    SPROMPT="%B%{^[[31m%}%r is correct? [n,y,a,e]:%{^[[m%}%b "
    [ -n "${REMOTEHOST}${SSH_CONNECTION}" ] && 
        PROMPT="%{^[[37m%}${HOST%%.*} ${PROMPT}"
    ;;
*)
    PROMPT="%{^[[31m%}%/%%%{^[[m%} "
    PROMPT2="%{^[[31m%}%_%%%{^[[m%} "
    SPROMPT="%{^[[31m%}%r is correct? [n,y,a,e]:%{^[[m%} "
    [ -n "${REMOTEHOST}${SSH_CONNECTION}" ] && 
        PROMPT="%{^[[37m%}${HOST%%.*} ${PROMPT}"
    ;;
esac

図2.6 プロンプトには色がつき、一般ユーザとrootで色合いが変わるよになっている。背景が白でも黒でも使えるような色合いにしてある

図2.7 sshでリモートログインしている場合にはプロンプトにホスト名も表示するようにしてある。相手のマシンでおかしな作業をするのを防止するためだ

色の指定は%{^[[31m%}の31の部分だ。ここの数字を変えるを表示される色もかわる。色が表示されるかどうか、どんな色が表示されるかはターミナルによって変わってくるので、このあたりを参考にして数字をかえてみてほしい。これはtcshのマニュアルだが、最後の方にLS_COLORSの説明があって、そこで数値と色の関係が説明されている。

ところで、上記設定をコピーして使ってみても、思ったようにはならないはず。「^[[31m/home/daichi%^[[m 」といったプロンプトになってしまうはずだ。これは"^["が実際には「エスケープ」といわれるものだからだ。

なので上記設定を~/.zshrcに書き込んだら、"^["の部分を削除してエスケープに置き換えればいい。viで編集するならCtrl-v ESCで入力できるし、EmacsならCtrl-q ESCで入力できる。エスケープを直接設定ファイルに記述することを嫌って、echoやprintfコマンドを使う場合もある。好きな方を選べばいい。ただ、コマンドだとプラットフォームごとに動いたり動かなかったりするので、ここでは直接書いて使っている。

パスの表示が左にあって移動するごとに長さがかわるのが気になる場合は、図2.8のように右に表示させることもできる。右に表示したいものについてはRPROMPT、RPROMPT2を設定すればいい。

右プロンプトの利点としては、入力がぶつかると消えるというのがある。zshのパワーをもってすればパスの省略表示といったことも簡単にできるのだが、筆者としてはこちらの方が好みかも。

図2.8 右にパスを表示させた場合 – 左プロンプトの長さがかわらないので便利

プロンプトと入力がぶつかると消える。便利だ。

この画像は、担当編集O氏のシェルで、設定は

PROMPT="%m:%n%% "
RPROMPT="[%~]"
SPROMPT="correct: %R -> %r ? "

となっている。なんのこだわりも見られないのはいかがなものか。

ターミナルのタイトル

ターミナルのタイトルも、プロンプトと同様こだわりたいところだ。タイトルを変更できるターミナルとそうでないものとあるのだが、仕組みとしてはリスト3.1のように書いておけばいい。この場合、ターミナルのタイトルに「ユーザ@ホスト:カレントディレクトリ」が表示されるようになる。

リスト3.1 ターミナルのタイトルに「ユーザ@ホスト:カレントディレクトリ」を表示させる設定

case "${TERM}" in
kterm*|xterm)
    precmd() {
        echo -ne "\033]0;${USER}@${HOST%%.*}:${PWD}\007"
    }
    ;;
esac

仕組みとしてはprecmd()組み込み関数を使って、こいつにターミナルへシーケンス文字を送信するコマンドを書いているというわけだ。

分岐構文を使ってkterm*とxtermに対象を絞っているのは、コンソールのようにタイトルバーの存在しないプラットフォームで処理をしないようにするためだ。愛用しているターミナルで動作しない場合、kterm*|xterm)のあたりを変更すればいいだろう。

今回はここまで。

最後に…… こういってはなんだが、実際問題シンプルな方が使いやすいですよ?

おまけ

今回説明した設定内容を設定ファイルにまとめたものを掲載しておく。ついでにbashとtcshで同じような設定をする場合の例も紹介しておく。zshが使えない環境での参考にしてみてほしい。

リスト4.1 今回の設定ファイルまとめ ~/.zshrc

## Environment variable configuration
#
# LANG
#
export LANG=ja_JP.UTF-8

## Default shell configuration
#
# set prompt
#
case ${UID} in
0)
    PROMPT="%B%{^[[31m%}%/#%{^[[m%}%b "
    PROMPT2="%B%{^[[31m%}%_#%{^[[m%}%b "
    SPROMPT="%B%{^[[31m%}%r is correct? [n,y,a,e]:%{^[[m%}%b "
    [ -n "${REMOTEHOST}${SSH_CONNECTION}" ] && 
        PROMPT="%{^[[37m%}${HOST%%.*} ${PROMPT}"
    ;;
*)
    PROMPT="%{^[[31m%}%/%%%{^[[m%} "
    PROMPT2="%{^[[31m%}%_%%%{^[[m%} "
    SPROMPT="%{^[[31m%}%r is correct? [n,y,a,e]:%{^[[m%} "
    [ -n "${REMOTEHOST}${SSH_CONNECTION}" ] && 
        PROMPT="%{^[[37m%}${HOST%%.*} ${PROMPT}"
    ;;
esac

# set terminal title including current directory
#
case "${TERM}" in
kterm*|xterm)
    precmd() {
        echo -ne "\033]0;${USER}@${HOST%%.*}:${PWD}\007"
    }
    ;;
esac

リスト4.2 bashで同じような設定をした場合 ~/.bashrc

## Environment variable configuration
#
# LANG
#
export LANG=ja_JP.UTF-8

## Default shell configuration
#
# set prompt
#
case ${UID} in
0)
    PS1='\[\033[1;31m\]${PWD}\$\[\033[0m\] '
    PS2='\[\033[1;31m\]>\[\033[0m\] '
    [ -n "${REMOTEHOST}${SSH_CONNECTION}" ] && PS1='\[\033[1;30m\]\h'" ${PS1}"
    ;;
*)
    PS1='\[\033[31m\]${PWD}\$\[\033[0m\] '
    PS2='\[\033[31m\]>\[\033[0m\] '
    [ -n "${REMOTEHOST}${SSH_CONNECTION}" ] && PS1='\[\033[37m\]\h'" ${PS1}"
    ;;
esac

# set terminal title including current directory
#
case "${TERM}" in
kterm*|xterm)
    PROMPT_COMMAND='echo -e "\033]0;'"${USER}@${HOSTNAME%%.*}:"'${PWD}\007\c"'
    ;;
esac

リスト4.3 tcshで同じような設定をした場合 ~/.tcshrc

## Environment variable configuration
#
# LANG
#
setenv LANG ja_JP.UTF-8

## Default shell configuration
#
# set prompt
#
if ( 0 == ${uid} ) then
    set prompt="%B%{\033[31m%}%/%#%{\033[m%}%b "
    set prompt2="%B%{\033[31m%}%R%#%{\033[m%}%b "
    set prompt3="%B%{\033[31m%}%R is correct? [y,n]:%{\033[m%}%b "
    if (${?REMOTEHOST} || ${?SSH_CONNECTION}) then
        set prompt="%{\033[37m%}${HOST:ar:au} ${prompt}"
    endif
else
    set prompt="%{\033[31m%}%/%%%{\033[m%} "
    set prompt2="%{\033[31m%}%R%%%{\033[m%} "
    set prompt3="%{\033[31m%}%R is correct? [y,n]:%{\033[m%} "
    if (${?REMOTEHOST} || ${?SSH_CONNECTION}) then
        set prompt="%{\033[37m%}${HOST:ar:au} ${prompt}"
    endif
endif

## terminal configuration
#
if ( ${?TERM} ) then
    switch ( "${TERM}" )
    case kterm:
    case kterm-color:
    case xterm:
        # set terminal title
        alias postcmd echo -n '"^[]2;${TERM:s/-/./:r} ${HOST:ar}:${cwd}^G"'

        breaksw
    endsw
endif

2/24

インデックス

連載目次
第24回 グッバイ野郎ども! コピペではじめるzshファイナル
第23回 コマンド補完設定 - アーキテクチャタイプ編
第22回 もってけ泥棒! コピペで始めるzsh - リターンズ
第21回 コマンド補完設定 - ファイルシステムタイプ編
第20回 コマンド補完設定 - cal/ncalコマンド編
第19回 コマンド補完設定 - trafshowコマンド編
第18回 コマンド補完設定 - daemonコマンド編(2)
第17回 コマンド補完設定 - daemonコマンド編(1)
第16回 拡張子ごとにコマンドを自動実行 - 「alias -s」
第15回 **で簡単ヒット!!! - 漢達への熱いお願い付き
第14回 zshとscreenで最強のターミナル環境
第13回 タブキーは最強だ - ファイルグロブもサクっと展開
第12回 一時ファイルはもういらない - プロセス置換
第11回 zshはエディタか? - 「zed」でお手軽編集
第10回 もってけ泥棒! コピペで始めるzsh
第9回 世界はモノクロからカラーへ
第8回 これは既にシェルを超えている…… zshの算術演算
第7回 ひと味違うzshのリダイレクト
第6回 漢はだまって先方予測 - あなたはこの機能使いこなせるか
第5回 「あーっ!」というそのときのために - 備えあれば憂いなしの設定集
第4回 コマンド履歴の検索~EmacsとVi、どっちも設定できるぜzsh
第3回 同じことを2度するなんて…… 自分の過去は利用しましょう
第2回 取りあえず、プロンプトを整えておく。カッコつけたいからね
第1回 最強のシェル、それは「zsh」

もっと見る



人気記事

一覧

イチオシ記事

新着記事