zsh で method_missing っぽいことをするには command_not_found_handler
きっかけ
「よく打つコマンドって typo しやすいね」「頭のスピードに手が追いついてない」「zsh 使ってて、 typo したときに勝手にコマンド名を修正してくれたらうれしいね」「zsh で ruby の method_missing みたいなの無いのかな?」とか発言があった。
「ゆっくり打てよ」 とか思いつつ、zsh だったら出来るだろうと思って man 見たらやっぱりあった。
command_not_found_handler について
command_not_found_handler ってのを使うとそういうのが出来るようになる。man zshmisc に書いてあった。
If no external command is found but a function command_not_found_handler exists the shell executes this function with all command line arguments. The function should return status zero if it successfully handled the command, or non-zero status if it failed. In the latter case the standard handling is applied: `command not found' is printed to standard error and the shell exits with status 127. Note that the handler is executed in a subshell forked to execute an external command, hence changes to directories, shell parameters, etc. have no effect on the main shell.
以下、適当な訳。
コマンドが見つからなくて、かつ command_not_found_handler 関数が定義されている場合、zsh はコマンドライン全部を引数としてその関数を呼び出す。この関数は、ハンドリングに成功した場合は 0、そうでない場合は非 0 を返すべきである。後者の場合、通常のエラーハンドリングが適用される。つまり、'command not found' が標準エラー出力に出力されて、シェルの戻り値は 127 になる。なお、このハンドラはサブシェルで実行される。そのため、cd 、変数などは元のシェルには影響を与えない。
実験
さっそく試してみる。
function command_not_found_handler() { # $0 がコマンド名 echo "!!! COMMAND NOT FOUND !!! $0" 1>&2 # 引数を表示する shift local a; for a in $@; do echo "arg : $a" 1>&2 done return 127 }
# notfound.zsh に書いて sorce する % source notfound.zsh # 適当に無いコマンドを実行する % hogehugapiyo arg1 arg2 arg3 !!! COMMAND NOT FOUND !!! hogehugapiyo arg : arg1 arg : arg2 arg : arg3 zsh: command not found: hogehugapiyo
ちゃんとできてる。うむっ。