.zshrcにこういうのありませんか?
autoload -U compinit
今回はこの autoload
が何をするものなのか解説します。
autoloadはシェル関数を読み込む
autoload
はシェル関数を 自動読み込み するシェルの組み込み関数です。上記のスクリプトの場合、 compinit
というシェル関数を自動読み込みします。
シェルコマンドは PATH
に入っていればそれだけで実行可能でしたが、シェル関数の場合は関数を定義しなければ使えません。 autoload
はファイルシステム上にある関数定義を読み込むための関数なのです。そして autoload
探索するディレクトリは FPATH
に入っています。
余談ですが FPATH
だと :
区切りの文字列、 fpath
だと配列になります。PATH
と path
と同じですね。
autoloadを使ってみる
% mkdir ~/functions
% FPATH="${HOME}/functions:${FPATH}" # ~/functionsをfpathに登録
% cat << EOF > ~/functions/test-func
#!/bin/zsh
echo Hello autoload
EOF
% ls ~/functions
. .. test-func
test-func という関数をfpathに登録したので実行してみます。
% where test-func
test-func not found
% autoload test-func
% where test-func # (1)
test-func () {
# undefined
builtin autoload -X
}
% test-func
Hello autoload
% where test-func # (2)
test-func () {
echo Hello autoload
}
たしかに ~/functions/test-func
の中身を持つ関数が作られました。
ところで (1) で表示される関数の中身がなんかおかしいですね。 builtin
は引数を強制的に組み込み関数名として解釈する関数なので、結局 autoload -X
をやっているだけですが、意図したものとは異なります。一方で一回関数を実行した後の (2) になると意図したものになっています。
実はこの -X
オプションがない場合、 autoload
コマンドは autoload という名前にも関わらず関数を登録するだけで、実体をロードしません。そして -X
があると、関数を実際にロードしてかつ即座に実行します。つまり、こうすることでzshは関数を遅延読み込みしているわけですね。
# 下の2行は即座に実行される点で同じ
autoload test-func; test-func
autoload -X test-func # 余計な中間関数がないので若干効率的
ロードだけして実行しない場合は +X
オプションを使います。先ほどの test-func
がまだロードされていない状態だとすると
% where test-func
test-func not found
% autoload +X test-func # ロードする
% where test-func # ロード済みになっている
test-func () {
echo Hello autoload
}
-X
と +X
オプションは覚えなくていいですが、zshrcでいくら autoload
しようが立ち上がり速度にはそこまで影響がない、ということは覚えておいて損は無さそうです。
-Uオプション
冒頭のコマンド
autoload -U compinit
ですが、この -U
オプションは一体何の働きをするのでしょう?個人的な観測範囲でいえば autoload
で -U
を使っていない場面をみたことがありません。
実はこのオプションは、展開される関数の内部で alias
の展開を しない ためのオプションです。つまり、これがないとあなたが適当に作ったalias
が干渉して、関数の動作が変わってしまう危険があるので、それを回避するために使うのです。
% alias foo='echo bar'
% cat << EOF > with-U > without-U
foo
EOF
% autoload -U with-U; with-U
zsh: command not found: foo
% autoload without-U; without-U
bar
というわけで autoload
を使うときは 必ず -U
オプションを使った方がよさそうです。
ちないに -U
と -X
は同時には使えないみたいです。なので -U
してかつ即座に実行したい場合は下記のようにしなければいけません。
autoload -U funcname; funcname
-X
オプションの説明に、シェルスクリプト内部でしか使うことないと思う、みたいなことが書いてあって、たぶんここら辺の事情が関係しているんだと予想してます。
もうちょっと追いかけてみる
autoload
みたいな組み込み関数についてのマニュアルは zshbuiltins(1) にあります。それによると
-X
,+X
,-w
なしのfunctions -u
と等しい
とあります。そして functions
は
-M
なしのtypeset -f
と等しい
つまり autoload
は typeset -fu
と等しい、ということになります。そもそも typeset
が何をするのかというと、簡単な話が変数宣言です。
例えば環境変数を設定する export
は typeset -gx
と同じです。 -g
はグローバルフラグで、 -x
は宣言した変数が環境変数であることを意味します。これによって宣言された変数が環境変数として外部からも利用可能になります。
で、問題の typeset -fu
ですが、 -f
は関数(function)である、という意味で -u
は(-f
と一緒に使っている場合)その関数を自動読み込み(autoloading)する、という意味です。
なるほどなるほど
合わせて読みたい
- zshmisc(1) の AUTOLOADING FUNCTIONS
- zshbuiltins(1)