zsh の menuselect 中に case-insensitive なインクリメンタルサーチをする
ちょっと zsh をカスタマイズしていたら止まらなくなってしまって、気に入らない挙動が出てきてしまったので自分でパッチを書いたという話。
zsh の機能で menuselect
zstyle ':completion:*:default' menu select=2
を設定している人も多いと多いと思うのだけれど、この場面で C-s または C-r を押すことでインクリメンタルサーチができる。
しかしこのとき case sensitive な検索しかできないのがどうにも我慢がならない。
C-s のときのコマンドが
history-incremental-search-forward
であることまでを突き止め、それで検索しまくったのだけど、
The search is case-insensitive if the search string does not have uppercase letters and no numeric argument was given.
http://zsh.sourceforge.net/Doc/Release/Zsh-Line-Editor.html
と書いてあるくせに menuselect の中ではそうでないらしい。
ぐぬぬ・・
で、仕方ないから自分でソースをいじることにした。
できたパッチが https://gist.github.com/1926791/e29ded0cb38ca88845649ef47579a2ce5d0a3fd7
Src/Zle/complist.c 内で strstr で一致を探していたのが悪く、大文字小文字を区別しない strstri を定義してこれを使うことにした。
(ちなみに本当の履歴のインクリメンタルサーチは Src/Zle/zle_hist.c 内の zlinecmp という関数を使っていて、今回もそれを使おうと思ったのだけどなんかうまくいかなかった。誰かいい実装できたら教えてください。)
このパッチを Homebrew なんかから使うときは
$ brew edit zsh
として、
def install
の上の行あたりに
def patches p = [] p << "https://raw.github.com/gist/1926791" return p end
と書いて
$ brew install zsh
すればよい。
ちなみに menuselect のとき、コマンド実行までに2回エンターを押さなければいけないことが我慢できない人も多いと思うのだけど、
bindkey -M menuselect '^M' .accept-line # (^M は quoted-insert)
のようにすることで1回でコマンドを実行できるようになる。これもっと早く知りたかったなあ。 (http://www.zsh.org/mla/users/2009/msg01018.html)