tl;dr
zle -N
してからの bindkey
を使え。
きっかけ
こちらで紹介されている
function percol-cdr () {
local selected_dir=$(cdr -l | awk '{ print $2 }' | percol --query "$LBUFFER")
if [ -n "$selected_dir" ]; then
BUFFER="cd ${selected_dir}"
zle accept-line
fi
zle clear-screen
}
zle -N percol-cdr
これを読み込んで、おもむろに percol-cdr
という 関数を 呼び出し、やった! これでぼくもナウいpercolユーザだ! ってやろうとすると
$ percol-cdr
percol-cdr:zle:4: widgets can only be called when ZLE is active
percol-cdr:zle:6: widgets can only be called when ZLE is active
って言われてcdできない。
when ZLE is active
is when?
なんかzshのソースコードを追いかけたり無駄なことをしていたんですけど、記事にもある通り要するに
bindkey '^@' percol-cdr
をして ^@
すれば想定したように動く。
zle の組込みコマンドはシェルから直接呼び出せない
BUFFER="ls -l"
zle accept-line
とシェルに打ち込んでも、同じようにエラーになる。一方で、デフォルトでは <ESC>-x
に割り当てられている execute-named-cmd
を呼び出し、
udzura@localhost ~$ <ESC>-x
execute: accept-line_
であればエラーにはならない(BUFFERは指定できないけど)。
zle、bindkeyの中でzshっぽい動きを呼び出すのに使う感じある
ZLE がアクティブになるのは、要するに「bindkeyで呼び出されたwidgetの内部処理のコンテクスト」である、ということと考えられる。
簡単な例で。
$ ls-l () { BUFFER='ls -l'; zle accept-line }
$ ls-l
ls-l:zle: widgets can only be called when ZLE is active
$ zle -N ls-l
$ bindkey '^[l' ls-l
$ <ESC>-l
# ls -l の結果がズラー
なので、zleのウィジェットを呼び出したりして色々操作したい時は、こんな感じが定石みたい。
- 関数作る
- 関数を
zle -N
でウィジェット登録する - ウィジェットを
bindkey
して使う
BUFFER
のような変数もそのコンテクストでのみ使えるものであるようだ。
つーか
まあ man zshzle の長ったらしい英文をちゃんと読めば分かる気がするけど...
この辺日本語情報ググっても出なくて、zshマスター各位はみんなちゃんと読んでるのだろうか...と思った。
まとめ
zsh弱者はoh-my-zshでも使ってろということなのだろう...
しかしこの辺の挙動が分かったので、今後はカスタムウィジェット作りまくってしまう気もする。