LoginSignup
46
37

More than 5 years have passed since last update.

widgets can only be called when ZLE is active とは何だったのか

Posted at

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でも使ってろということなのだろう...

しかしこの辺の挙動が分かったので、今後はカスタムウィジェット作りまくってしまう気もする。

46
37
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
46
37