zsh のシェルスクリプトを作るとき、基本的には普通のシェルスクリプトとして書く。「普通」というのは、1行目に #!/bin/zsh
と書いてあって、今のシェルとは別プロセスで動かすスクリプトのことだ。
例えばこんな感じ。
#!/bin/zsh
echo "Hello World"
# 使うとき
% chmod 755 script_sample.zsh
% ./script_sample.zsh
Hello World
でも、そうではなくて source
して使うスクリプトを書くことがある。
homecd () {
cd
ls
}
# 使うとき
% source source_sample.zsh
% homecd
Desktop/ bin/ local/ tmp/ vimfiles/
Dropbox/ etc/ var/ work/
特に、cd や bindkey など、今動いているシェル上で副作用のある処理を行いたいときは source
を使わないとうまくいかないだろう。
一方、source
にはこんなデメリットがある。
- .zshrc でいっぱい
source
するとzsh の起動が遅くなる - 現在動いているシェルの alias 設定の影響を受ける
特に2つめが厄介だ。例えば grep
とかしたときに、alias grep='grep -E'
なんか設定してあったら正規表現の意味が変わってしまう。一応 command grep
とすれば alias を設定していない元の grep
を実行できるけど、いちいちそう書くのも手間だ。
そんなときは autoload
を使う形に書き換えるとうまくいく。
autoload
というのは「関数本体の読み込みを実行する時まで遅らせる」という zsh の機能のこと。これで ~/.zshrc にいっぱい書いても起動が遅くならないですむ。さらに alias を無効する(現在の alias の影響を受けない)ようにもできる。これで変なことを気にしなくて良くなるので、関数が書きやすくなる。
基本的な例
まずは hello_autoload
という名前の関数を autoload する例を見てみる。
まず、以下の内容でファイルを作成する。ファイル名は hello_autoload とする。このファイル名が実際に実行するときの関数名になる。
echo "Hello Autoload!"
普通、関数の定義は
hello_autoload () {
# 関数の中身
}
みたいに書くんだけど、 autoload
するときは関数の中身だけ書くことに注意する。
この hello_autoload ファイルを $fpath の通ったところに配置すれば準備完了。
後は ~/.zshrc で autoload して、
autoload hello_autoload
使いたい時に呼びだせば OK。
% hello_autoload
Hello Autoload!
実践的な例
次は実際にプラグインっぽく作るときの書き方を見てみる。今回は「指定したディレクトリに移動して ls
する」という関数を作ってみる。名前は cdls
にする。
cdls
という名前で次のファイルを作成する。
cd $1
ls
ファイルを置く場所はどこでもいいんだけど、今回は ~/zsh/functions/Cdls/ とした。ディレクトリ名も何でもいいんだけど、慣習として先頭は大文字にするようだ。
次に .zshrc で fpath を通して autoload
する。
fpath=(~/zsh/functions/*(N-/) $fpath)
autoload -Uz cdls
autoload
で -U
と -z
というオプションを指定してる。
-U
は、呼び出し側のシェルで alias
設定を設定していたとしても、中の関数側ではその影響を受けなくなるというオプション。ls
は alias を設定してることが多いと思うけど、この場合はそのままの ls
が実行される。
-z
は関数を zsh 形式で読み込むというオプション。代わりに -k
を指定すると ksh 形式で読み込むようになる。普通は zsh 形式で関数を書くので -z
と指定しておけば問題ない。
後は適当に source ~/.zshrc して、使いたい時に呼び出すだけだ。
% cdls
Desktop Dropbox bin etc local tmp var vimfiles work
% pwd
/home/mollifier
% cdls ~/work
github-sandbox javascript nodejs scala vim zsh
% pwd
/home/mollifier/work
うまくいってる。
これ以降、autoload が必要なスクリプトを追加するときは同じように ~/zsh/functions/ の下にディレクトリを作って配置すれば良い。
fpath=(~/zsh/functions/*(N-/) $fpath)
という設定をしているので、~/zsh/functions/ の下にディレクトリがあればそこに勝手に fpath が通るようになってる。なので fpath の設定は書きなおさなくても OK。
こんな感じで source
しないようにすればもっと便利になると思うので試してみてください!