おすすめzsh設定 - 2011-09-05 - ククログ

ククログ

株式会社クリアコード > ククログ > おすすめzsh設定

おすすめzsh設定

他の人がzshを使っているのを見ていると、「もっと便利に使えるのに」と、もやっとしたり、「え、その便利な機能ってなに?」と、発見があったりします。だれかに「この設定をすると便利ですよ」と話しやすくするために、今のzshのおすすめ設定をここに記しておきます。

もし、Emacsも使っている場合はおすすめEmacs設定もどうぞ。

ディレクトリ構成

長年漬け込んできたzshの設定がそこそこの量になっているので、以下のようなディレクトリ構成にして分類しています。主に、zsh標準機能の設定と追加パッケージの設定を分けるためにこうしています。

~
├── .zshrc                    # シェルを起動する毎に読み込まれる。
│                               # ~/.zsh.d/zshrcを読み込んで
│                               # 標準機能の追加設定を行う。
├── .zshenv                   # ログイン時に一度だけ読み込まれる。
│                               # ~/.zsh.d/zshenvを読み込んで
│                               # 追加設定を行う。
└── .zsh.d                    # zsh関連のファイル置き場。
       ├── config             # 標準機能以外の設定を置くディレクトリ。
       │    └── packages.zsh # 追加パッケージの設定をするファイル。
       ├── zshrc              # おすすめ~/.zshrc設定。
       ├── zshenv             # おすすめ~/.zshenv設定。
       ├── package.zsh        # パッケージ管理システム。
       └── packages           # パッケージをインストールするディレクトリ。

おすすめ設定の使い方

このうち、~/.zsh.d/以下にあるzshrczshenvは一般的なおすすめ設定となっていて、GitHubに置いてあります。

GitHubにあるおすすめ設定は以下のようにして使えます。(以下のコマンドをそのまま実行すると既存の~/.zshrc~/.zshenvを上書きするので注意してください。)

% git clone https://github.com/clear-code/zsh.d.git ~/.zsh.d
% echo "source ~/.zsh.d/zshrc" > ~/.zshrc
% echo "source ~/.zsh.d/zshenv" > ~/.zshenv

これらのおすすめ設定は~/.zshrc~/.zshenvの先頭 で読み込んで、その後でカスタマイズすることを想定しています。 例えばこんな感じです。

~/.zshrc:

### ~/.zshrc

# おすすめ設定を読み込む。
source ~/.zsh.d/zshrc

# これより↓に自分用の設定を書く。
#   setopt ...
#   alias ...
# など

~/.zshenv:

### ~/.zshenv

# おすすめ設定を読み込む。
source ~/.zsh.d/zshenv

# これより↓に自分用の設定を書く。
#   export EMAIL="..."
# など

~/.zshrc~/.zshenvの使い分け

~/.zshrc~/.zshenvは以下のように使い分けます。

  • 対話的に使うときだけ必要なものは~/.zshrc
  • 常に使うものは~/.zshenv

対話的以外にどういう場面で使うかというと、例えば、Emacs上からM-!でコマンドを実行するときです。このときは~/.zshenvのみが読み込まれて~/.zshrcは読み込まれません。

~/.zshenvのおすすめ設定

パスやEmacsなどからも使うページャやgrepなどのコマンドの設定、環境変数の設定などをします。設定の説明はコメントを見てください。

パスの設定

(N-/)は便利なので覚えておいて損はありません。

## 重複したパスを登録しない。
typeset -U path
## (N-/): 存在しないディレクトリは登録しない。
##    パス(...): ...という条件にマッチするパスのみ残す。
##            N: NULL_GLOBオプションを設定。
##               globがマッチしなかったり存在しないパスを無視する。
##            -: シンボリックリンク先のパスを評価。
##            /: ディレクトリのみ残す。
path=(# システム用
      /bin(N-/)
      # 自分用
      $HOME/local/bin(N-/)
      # Debian GNU/Linux用
      /var/lib/gems/*/bin(N-/)
      # MacPorts用
      /opt/local/bin(N-/)
      # Solaris用
      /opt/csw/bin(N-/)
      /usr/sfw/bin(N-/)
      # Cygwin用
      /cygdrive/c/meadow/bin(N-/)
      # システム用
      /usr/local/bin(N-/)
      /usr/bin(N-/)
      /usr/games(N-/))

sudo時のパスの設定

sudoを使うときはsbinもパスに入れたいです。ただ、ここで設定したからといって実際にsudoで使われるわけではありません。後で~/.zshrcで設定するsudo時の補完用に使います。そのため、~/.zshenvではなく~/.zshrcで設定したほうがよい気もしますが、パスなので~/.zshenvに入れました。

typeset -Tは便利なので覚えておいて損はないと思います。

## -x: export SUDO_PATHも一緒に行う。
## -T: SUDO_PATHとsudo_pathを連動する。
typeset -xT SUDO_PATH sudo_path
## 重複したパスを登録しない。
typeset -U sudo_path
## (N-/): 存在しないディレクトリは登録しない。
##    パス(...): ...という条件にマッチするパスのみ残す。
##            N: NULL_GLOBオプションを設定。
##               globがマッチしなかったり存在しないパスを無視する。
##            -: シンボリックリンク先のパスを評価。
##            /: ディレクトリのみ残す。
sudo_path=({,/usr/pkg,/usr/local,/usr}/sbin(N-/))

man時のパスの設定

(ほとんどありませんが)Emacs上でmanを読むこともあるためman用のパスも~/.zshenvで設定します。

## 重複したパスを登録しない。
typeset -U manpath
## (N-/) 存在しないディレクトリは登録しない。
##    パス(...): ...という条件にマッチするパスのみ残す。
##            N: NULL_GLOBオプションを設定。
##               globがマッチしなかったり存在しないパスを無視する。
##            -: シンボリックリンク先のパスを評価。
##            /: ディレクトリのみ残す。
manpath=(# 自分用
         $HOME/local/share/man(N-/)
         # MacPorts用
         /opt/local/share/man(N-/)
         # Solaris用
         /opt/csw/share/man(N-/)
         /usr/sfw/share/man(N-/)
         # システム用
         /usr/local/share/man(N-/)
         /usr/share/man(N-/))

Rubyの設定

Rubyのライブラリを開発するときは./lib$LOAD_PATHに入っていると便利なので、その設定をしています。

## ライブラリのロードパス
### -x: export RUBYLIBも一緒に行う。
### -T: RUBYLIBとruby_pathを連動する。
typeset -xT RUBYLIB ruby_path
### 重複したパスを登録しない。
typeset -U ruby_path
### パスを設定
ruby_path=(# カレントディレクトリのライブラリを優先する
           ./lib)

Pythonの設定

Pythonのライブラリを開発するときは./libsys.pathに入っていると便利なので、その設定をしています。

## ライブラリのロードパス
### -x: export PYTHONPATHも一緒に行う。
### -T: PYTHONPATHとpython_pathを連動する。
typeset -xT PYTHONPATH pyhon_path
### 重複したパスを登録しない。
typeset -U python_path
### パスを設定。
python_path=(# カレントディレクトリのライブラリを優先する
             ./lib)

pkg-configの設定

pkg-configをサポートしたライブラリを使った開発するときの設定です。

## .pcのロードパス
### -x: export PKG_CONFIG_PATHも一緒に行う。
### -T: PKG_CONFIG_PATHとpkg_config_pathを連動する。
typeset -xT PKG_CONFIG_PATH pkg_config_path
### 重複したパスを登録しない。
typeset -U pkg_config_path
### パスを設定。
### (N-/) 存在しないディレクトリは登録しない。
###    パス(...): ...という条件にマッチするパスのみ残す。
###            N: NULL_GLOBオプションを設定。
###               globがマッチしなかったり存在しないパスを無視する。
###            -: シンボリックリンク先のパスを評価。
###            /: ディレクトリのみ残す。
pkg_config_path=(# 自分用
                 $HOME/local/lib/pkgconfig(N-/)
                 # MacPorts用
                 /opt/local/lib/pkgconfig(N-/))

ページャの設定

エンコーディングを変換できることが便利なのでlvを優先して使います。

if type lv > /dev/null 2>&1; then
    ## lvを優先する。
    export PAGER="lv"
else
    ## lvがなかったらlessを使う。
    export PAGER="less"
fi

lvの設定

単に「lv」としただけでもいい感じに動くようにします。

if [ "$PAGER" = "lv" ]; then
    ## -c: ANSIエスケープシーケンスの色付けなどを有効にする。
    ## -l: 1行が長くと折り返されていても1行として扱う。
    ##     (コピーしたときに余計な改行を入れない。)
    export LV="-c -l"
else
    ## lvがなくてもlvでページャーを起動する。
    alias lv="$PAGER"
fi

grepの設定

grepはGNU grepを使い、便利な機能は単に「grep」としただけで使えるようにします。一番便利なのは--color=autoです。

## GNU grepがあったら優先して使う。
if type ggrep > /dev/null 2>&1; then
    alias grep=ggrep
fi
## デフォルトオプションの設定
export GREP_OPTIONS
### バイナリファイルにはマッチさせない。
GREP_OPTIONS="--binary-files=without-match"
### grep対象としてディレクトリを指定したらディレクトリ内を再帰的にgrepする。
GREP_OPTIONS="--directories=recurse $GREP_OPTIONS"
### 拡張子が.tmpのファイルは無視する。
GREP_OPTIONS="--exclude=\*.tmp $GREP_OPTIONS"
## 管理用ディレクトリを無視する。
if grep --help | grep -q -- --exclude-dir; then
    GREP_OPTIONS="--exclude-dir=.svn $GREP_OPTIONS"
    GREP_OPTIONS="--exclude-dir=.git $GREP_OPTIONS"
    GREP_OPTIONS="--exclude-dir=.deps $GREP_OPTIONS"
    GREP_OPTIONS="--exclude-dir=.libs $GREP_OPTIONS"
fi
### 可能なら色を付ける。
if grep --help | grep -q -- --color; then
    GREP_OPTIONS="--color=auto $GREP_OPTIONS"
fi

エディタの設定

visudoなど、エディタが必要になったときはvimを使うようにします。

## vimを使う。
export EDITOR=vim
## vimがなくてもvimでviを起動する。
if ! type vim > /dev/null 2>&1; then
    alias vim=vi
fi

メールアドレスの設定

~/.zsh.d/emailまたは~/.emailにメールアドレスを書いておくと、そのファイルの中身を環境変数EMAILに設定します。メールアドレスはそれぞれ違うためこのように設定するようにしました。

## ~/.zsh.d/email → ~/.emailの順に探して最初に見つかったファイルから読み込む。
## (N-.): 存在しないファイルは登録しない。
##    パス(...): ...という条件にマッチするパスのみ残す。
##            N: NULL_GLOBオプションを設定。
##               globがマッチしなかったり存在しないパスを無視する。
##            -: シンボリックリンク先のパスを評価。
##            .: 通常のファイルのみ残す。
email_files=(~/.zsh.d/email(N-.)
             ~/.email(N-.))
for email_file in ${email_files}; do
    export EMAIL=$(cat "$email_file")
    break
done

~/.zshrcのおすすめ設定

補完やaliasなど対話的に使ったときに便利な機能の設定をします。こちらも設定の説明はコメントを見てください。

キーバインド

環境変数EDITORにvimと設定しているとviキーバインドになってしまうので、Emacsキーバインドを使うように明示的に指定しています。

## Emacsキーバインドを使う。
bindkey -e

ディレクトリ移動

cdの機能を拡張します。chpwd_functionsは覚えておいて損はないと思います。直接chpwdを定義するよりも追加の設定が簡単になります。

## ディレクトリ名だけでcdする。
setopt auto_cd
## cdで移動してもpushdと同じようにディレクトリスタックに追加する。
setopt auto_pushd
## カレントディレクトリ中に指定されたディレクトリが見つからなかった場合に
## 移動先を検索するリスト。
cdpath=(~)
## ディレクトリが変わったらディレクトリスタックを表示。
chpwd_functions=($chpwd_functions dirs)

ヒストリ

ヒストリはとてもよく使うため基本的に過去のコマンドラインは消えないようにします。

## ヒストリを保存するファイル
HISTFILE=~/.zsh_history
## メモリ上のヒストリ数。
## 大きな数を指定してすべてのヒストリを保存するようにしている。
HISTSIZE=10000000
## 保存するヒストリ数
SAVEHIST=$HISTSIZE
## ヒストリファイルにコマンドラインだけではなく実行時刻と実行時間も保存する。
setopt extended_history
## 同じコマンドラインを連続で実行した場合はヒストリに登録しない。
setopt hist_ignore_dups
## スペースで始まるコマンドラインはヒストリに追加しない。
setopt hist_ignore_space
## すぐにヒストリファイルに追記する。
setopt inc_append_history
## zshプロセス間でヒストリを共有する。
setopt share_history
## C-sでのヒストリ検索が潰されてしまうため、出力停止・開始用にC-s/C-qを使わない。
setopt no_flow_control

プロンプト

以下のような2段プロンプトにします。1段目にはできるだけ現在情報を多めに表示して、後から実行履歴をさかのぼって見たときに有意義な情報が残るようにします。プロンプト内にコマンドの実行ステータスを入れるようにしているのでprint_exit_statusオプションは設定していません。

-(user@debian)-(0)-<2011/09/01 00:54>--------------------[/home/user]-
-[84](1)%                                                         [~]

プロンプトで多くの機能を使えるようにします。

## PROMPT内で変数展開・コマンド置換・算術演算を実行する。
setopt prompt_subst
## PROMPT内で「%」文字から始まる置換機能を有効にする。
setopt prompt_percent
## コピペしやすいようにコマンド実行後は右プロンプトを消す。
setopt transient_rprompt

使っていませんが、256色用の色を生成する機能です。

## 256色生成用便利関数
### red: 0-5
### green: 0-5
### blue: 0-5
color256()
{
    local red=$1; shift
    local green=$2; shift
    local blue=$3; shift

    echo -n $[$red * 36 + $green * 6 + $blue + 16]
}

fg256()
{
    echo -n $'\e[38;5;'$(color256 "$@")"m"
}

bg256()
{
    echo -n $'\e[48;5;'$(color256 "$@")"m"
}

プロンプトにたくさんの情報を盛り込もうと頑張っています。「%」が多くてとても読みづらいですね。

## プロンプトの作成
### ↓のようにする。
###   -(user@debian)-(0)-<2011/09/01 00:54>--------------------[/home/user]-
###   -[84](0)%                                                         [~]

## バージョン管理システムの情報も表示する
autoload -Uz vcs_info
zstyle ':vcs_info:*' formats \
    '(%{%F{white}%K{green}%}%s%{%f%k%})-[%{%F{white}%K{blue}%}%b%{%f%k%}]'
zstyle ':vcs_info:*' actionformats \
    '(%{%F{white}%K{green}%}%s%{%f%k%})-[%{%F{white}%K{blue}%}%b%{%f%k%}|%{%F{white}%K{red}%}%a%{%f%k%}]'

### プロンプトバーの左側
###   %{%B%}...%{%b%}: 「...」を太字にする。
###   %{%F{cyan}%}...%{%f%}: 「...」をシアン色の文字にする。
###   %n: ユーザ名
###   %m: ホスト名(完全なホスト名ではなくて短いホスト名)
###   %{%B%F{white}%(?.%K{green}.%K{red})%}%?%{%f%k%b%}:
###                           最後に実行したコマンドが正常終了していれば
###                           太字で白文字で緑背景にして異常終了していれば
###                           太字で白文字で赤背景にする。
###   %{%F{white}%}: 白文字にする。
###     %(x.true-text.false-text): xが真のときはtrue-textになり
###                                偽のときはfalse-textになる。
###       ?: 最後に実行したコマンドの終了ステータスが0のときに真になる。
###       %K{green}: 緑景色にする。
###       %K{red}: 赤景色を赤にする。
###   %?: 最後に実行したコマンドの終了ステータス
###   %{%k%}: 背景色を元に戻す。
###   %{%f%}: 文字の色を元に戻す。
###   %{%b%}: 太字を元に戻す。
###   %D{%Y/%m/%d %H:%M}: 日付。「年/月/日 時:分」というフォーマット。
prompt_bar_left_self="(%{%Y/%m/%d %H:%M}: 日付。「年/月/日 時:分」というフォーマット。
prompt_bar_left_self="(%{%B%}%n%{%b%}%{%F{cyan}%}@%{%f%}%{%B%}%m%{%b%})"
prompt_bar_left_status="(%{%B%F{white}%(?.%K{green}.%K{red})%}%?%{%k%f%b%})"
prompt_bar_left_date="<%{%B%}%D{%Y/%m/%d %H:%M}%{%Y/%m/%d %H:%M}%{%b%}>"
prompt_bar_left="-${prompt_bar_left_self}-${prompt_bar_left_status}-${prompt_bar_left_date}-"
### プロンプトバーの右側
###   %{%B%K{magenta}%F{white}%}...%{%f%k%b%}:
###       「...」を太字のマジェンタ背景の白文字にする。
###   %d: カレントディレクトリのフルパス(省略しない)
prompt_bar_right="-[%{%B%K{magenta}%F{white}%}%d%{%f%k%b%}]-"

### 2行目左にでるプロンプト。
###   %h: ヒストリ数。
###   %(1j,(%j),): 実行中のジョブ数が1つ以上ある場合だけ「(%j)」を表示。
###     %j: 実行中のジョブ数。
###   %{%B%}...%{%b%}: 「...」を太字にする。
###   %#: 一般ユーザなら「%」、rootユーザなら「#」になる。
prompt_left="-[%h]%(1j,(%j),)%{%B%}%#%{%b%} "

## プロンプトフォーマットを展開した後の文字数を返す。
## 日本語未対応。
count_prompt_characters()
{
    # print:
    #   -P: プロンプトフォーマットを展開する。
    #   -n: 改行をつけない。
    # sed:
    #   -e $'s/\e\[[0-9;]*m//g': ANSIエスケープシーケンスを削除。
    # sed:
    #   -e 's/ //g': *BSDやMac OS Xのwcは数字の前に空白を出力するので削除する。
    print -n -P -- "$1" | sed -e $'s/\e\[[0-9;]*m//g' | wc -m | sed -e 's/ //g'
}

## プロンプトを更新する。
update_prompt()
{
    # プロンプトバーの左側の文字数を数える。
    # 左側では最後に実行したコマンドの終了ステータスを使って
    # いるのでこれは一番最初に実行しなければいけない。そうし
    # ないと、最後に実行したコマンドの終了ステータスが消えて
    # しまう。
    local bar_left_length=$(count_prompt_characters "$prompt_bar_left")
    # プロンプトバーに使える残り文字を計算する。
    # $COLUMNSにはターミナルの横幅が入っている。
    local bar_rest_length=$[COLUMNS - bar_left_length]

    local bar_left="$prompt_bar_left"
    # パスに展開される「%d」を削除。
    local bar_right_without_path="${prompt_bar_right:s/%d//}"
    # 「%d」を抜いた文字数を計算する。
    local bar_right_without_path_length=$(count_prompt_characters "$bar_right_without_path")
    # パスの最大長を計算する。
    #   $[...]: 「...」を算術演算した結果で展開する。
    local max_path_length=$[bar_rest_length - bar_right_without_path_length]
    # パスに展開される「%d」に最大文字数制限をつける。
    #   %d -> %(C,%${max_path_length}<...<%d%<<,)
    #     %(x,true-text,false-text):
    #         xが真のときはtrue-textになり偽のときはfalse-textになる。
    #         ここでは、「%N<...<%d%<<」の効果をこの範囲だけに限定させる
    #         ために用いているだけなので、xは必ず真になる条件を指定している。
    #       C: 現在の絶対パスが/以下にあると真。なので必ず真になる。
    #       %${max_path_length}<...<%d%<<:
    #          「%d」が「${max_path_length}」カラムより長かったら、
    #          長い分を削除して「...」にする。最終的に「...」も含めて
    #          「${max_path_length}」カラムより長くなることはない。
    bar_right=${prompt_bar_right:s/%d/%(C,%${max_path_length}<...<%d%<<,)/}
    # 「${bar_rest_length}」文字分の「-」を作っている。
    # どうせ後で切り詰めるので十分に長い文字列を作っているだけ。
    # 文字数はざっくり。
    local separator="${(l:${bar_rest_length}::-:)}"
    # プロンプトバー全体を「${bar_rest_length}」カラム分にする。
    #   %${bar_rest_length}<<...%<<:
    #     「...」を最大で「${bar_rest_length}」カラムにする。
    bar_right="%${bar_rest_length}<<${separator}${bar_right}%<<"

    # プロンプトバーと左プロンプトを設定
    #   "${bar_left}${bar_right}": プロンプトバー
    #   $'\n': 改行
    #   "${prompt_left}": 2行目左のプロンプト
    PROMPT="${bar_left}${bar_right}"$'\n'"${prompt_left}"
    # 右プロンプト
    #   %{%B%F{white}%K{green}}...%{%B%F{white}%K{green}}...%{%k%f%b%}:
    #       「...」を太字で緑背景の白文字にする。
    #   %~: カレントディレクトリのフルパス(可能なら「~」で省略する)
    RPROMPT="[%{%B%F{white}%K{magenta}%}%~%{%k%f%b%}]"

    # バージョン管理システムの情報を取得する。
    LANG=C vcs_info >&/dev/null
    # バージョン管理システムの情報があったら右プロンプトに表示する。
    if [ -n "$vcs_info_msg_0_" ]; then
        RPROMPT="${vcs_info_msg_0_}-${RPROMPT}"
    fi
}

## コマンド実行前に呼び出されるフック。
precmd_functions=($precmd_functions update_prompt)

補完

zshのとても大事な機能です。

## 初期化
autoload -U compinit
compinit

補完候補をグループ化するとぐっと見やすくなります。

## 補完方法毎にグループ化する。
### 補完方法の表示方法
###   %B...%b: 「...」を太字にする。
###   %d: 補完方法のラベル
zstyle ':completion:*' format '%B%d%b'
zstyle ':completion:*' group-name ''

補完候補が多いときや日本語のファイル名のときはメニューから選択できると便利です。selectの他にtrueも設定できるのですが、それを設定するとすぐに補完された状態になり使い勝手が悪いため設定していません。

## 補完侯補をメニューから選択する。
### select=2: 補完候補を一覧から選択する。
###           ただし、補完候補が2つ以上なければすぐに補完する。
zstyle ':completion:*:default' menu select=2

パスを補完しているときにディレクトリやシンボリックリンクがパッと見てわかるので便利です。

## 補完候補に色を付ける。
### "": 空文字列はデフォルト値を使うという意味。
zstyle ':completion:*:default' list-colors ""

大文字を入力しなくても大文字の補完候補が出てきて便利です。また、Emacsのpartial-completion-modeのようにも補完できて、public_htmlをp_で補完できて便利です。

## 補完候補がなければより曖昧に候補を探す。
### m:{a-z}={A-Z}: 小文字を大文字に変えたものでも補完する。
### r:|[._-]=*: 「.」「_」「-」の前にワイルドカード「*」があるものとして補完する。
zstyle ':completion:*' matcher-list 'm:{a-z}={A-Z} r:|[._-]=*'

多めに補完方法を使っています。

## 補完方法の設定。指定した順番に実行する。
### _oldlist 前回の補完結果を再利用する。
### _complete: 補完する。
### _match: globを展開しないで候補の一覧から補完する。
### _history: ヒストリのコマンドも補完候補とする。
### _ignored: 補完候補にださないと指定したものも補完候補とする。
### _approximate: 似ている補完候補も補完候補とする。
### _prefix: カーソル以降を無視してカーソル位置までで補完する。
zstyle ':completion:*' completer \
    _oldlist _complete _match _history _ignored _approximate _prefix

細々と便利な設定です。

## 補完候補をキャッシュする。
zstyle ':completion:*' use-cache yes
## 詳細な情報を使う。
zstyle ':completion:*' verbose yes
## sudo時にはsudo用のパスも使う。
zstyle ':completion:sudo:*' environ PATH="$SUDO_PATH:$PATH"

## カーソル位置で補完する。
setopt complete_in_word
## globを展開しないで候補の一覧から補完する。
setopt glob_complete
## 補完時にヒストリを自動的に展開する。
setopt hist_expand
## 補完候補がないときなどにビープ音を鳴らさない。
setopt no_beep
## 辞書順ではなく数字順に並べる。
setopt numeric_glob_sort

展開

configureを使うときに便利です。

## --prefix=~/localというように「=」の後でも
## 「~」や「=コマンド」などのファイル名展開を行う。
setopt magic_equal_subst

あまり必要な機会はありませんが、設定しています。

## 拡張globを有効にする。
## glob中で「(#...)」という書式で指定する。
setopt extended_glob
## globでパスを生成したときに、パスがディレクトリだったら最後に「/」をつける。
setopt mark_dirs

ジョブ

別の端末からgdbでアタッチするときにプロセスIDがわかると便利です。

## jobsでプロセスIDも出力する。
setopt long_list_jobs

実行時間

明示的にtimeを使わずに済んで便利です。

## 実行したプロセスの消費時間が3秒以上かかったら
## 自動的に消費時間の統計情報を表示する。
REPORTTIME=3

ログイン・ログアウト

クラックされたときにすぐに気づけ(ることがあり)ます。

## 全てのユーザのログイン・ログアウトを監視する。
watch="all"
## ログイン時にはすぐに表示する。
log

## ^Dでログアウトしないようにする。
setopt ignore_eof

単語

C-wで単語単位で削除するときにパスの1コンポーネントだけ削除できて便利です。M-f/M-bで単語移動をする人も便利でしょう。

## 「/」も単語区切りとみなす。
WORDCHARS=${WORDCHARS:s,/,,}

alias

LGが特に便利です。

## ページャーを使いやすくする。
### grep -r def *.rb L -> grep -r def *.rb |& lv
alias -g L="|& $PAGER"
## grepを使いやすくする。
alias -g G='| grep'
## 後はおまけ。
alias -g H='| head'
alias -g T='| tail'
alias -g S='| sed'

rrをよく使います。

## 完全に削除。
alias rr="command rm -rf"
## ファイル操作を確認する。
alias rm="rm -i"
alias cp="cp -i"
alias mv="mv -i"

poをよく使います。pdauto_pushdを設定しているため使いません。

## pushd/popdのショートカット。
alias pd="pushd"
alias po="popd"

素のlsを使うことはほとんどなく、いつもlaを使っています。

## lsとpsの設定
### ls: できるだけGNU lsを使う。
### ps: 自分関連のプロセスのみ表示。
case $(uname) in
    *BSD|Darwin)
        if [ -x "$(which gnuls)" ]; then
            alias ls="gnuls"
            alias la="ls -lhAF --color=auto"
        else
            alias la="ls -lhAFG"
        fi
        alias ps="ps -fU$(whoami)"
        ;;
    SunOS)
        if [ -x "`which gls`" ]; then
            alias ls="gls"
            alias la="ls -lhAF --color=auto"
        else
            alias la="ls -lhAF"
        fi
        alias ps="ps -fl -u$(/usr/xpg4/bin/id -un)"
        ;;
    *)
        alias la="ls -lhAF --color=auto"
        alias ps="ps -fU$(whoami) --forest"
        ;;
esac

ウィンドウタイトル

タブを切り替えているときに便利です。

## 実行中のコマンドとユーザ名とホスト名とカレントディレクトリを表示。
update_title() {
    local command_line=
    typeset -a command_line
    command_line=${(z)2}
    local command=
    if [ ${(t)command_line} = "array-local" ]; then
        command="$command_line[1]"
    else
        command="$2"
    fi
    print -n -P "\e]2;"
    echo -n "(${command})"
    print -n -P " %n@%m:%~\a"
}
## X環境上でだけウィンドウタイトルを変える。
if [ -n "$DISPLAY" ]; then
    preexec_functions=($preexec_functions update_title)
fi

おまけ: package.zshの使い方

GitHubにあるおすすめ設定の中にpackage.zshという簡単なパッケージ管理1システムも入っています。これを使えばGitHub上にあるzshを拡張するパッケージを簡単にインストールすることができます。例えば、auto-fuを使う場合は以下のようにします。auto-fuの設定をするファイルが~/.zsh.d/config/packages.zshなのはauto-fuがzshの標準機能ではなく追加パッケージだからです。このポリシーについてはこのページの先頭にある「ディレクトリ構成」のところを見直してください。

~/.zsh.d/config/packages.zsh:

# -*- sh -*-

# パッケージ管理システムを読み込む。
source ~/.zsh.d/package.zsh

# パッケージがインストールされていなければGitHubからcloneしてくる。
package-install github hchbaw/auto-fu.zsh
# パッケージを読み込む。
source $(package-directory hchbaw/auto-fu.zsh)/auto-fu.zsh
# auto-fuを初期化する。
zle-line-init() {
    auto-fu-init
}
zle -N zle-line-init
zle -N zle-keymap-select auto-fu-zle-keymap-select

# auto-fuをカスタマイズする。
## Enterを押したときは自動補完された部分を利用しない。
afu+cancel-and-accept-line() {
    ((afu_in_p == 1)) && { afu_in_p=0; BUFFER="$buffer_cur" }
    zle afu+accept-line
}
zle -N afu+cancel-and-accept-line
bindkey -M afu "^M" afu+cancel-and-accept-line

~/.zshrc:

### ~/.zshrc

# おすすめ設定を読み込む。
source ~/.zsh.d/zshrc

# 追加パッケージの設定を読み込む。
source ~/.zsh.d/config/packages.zsh

これで次にzshを起動するとauto-fuが使えるようになっています。

まとめ

長年漬け込んできたzshの設定を紹介しました。

ここで紹介した内容はGitHubに置いておいたので、興味がある人は試してみてください。

おすすめEmacs設定もありますので、Emacsも使っているひとはそちらも試してみてください。

  1. 「管理」というより「インストール」というか「ダウンロード」。