これは "今年書いて良かった dot files アドベントカレンダー" 14日目の記事です.
Zsh には bindkey という機能があって、ターミナルから普通にコマンドを入力する以外に Ctrl で装飾したようなキー入力から関数を呼び出すことが出来る.
例えば以下を .zshrc に書いておくと、Ctrl-h で挨拶が出来る.
# test.zsh
greeting() {
    echo Hello
}
zle -N greeting
bindkey "^H" greetingこれはあくまで例だから有用性はない. Ctrl-h するとその時点で echo が実行されるので邪魔.
cympfh% _
この時点で Ctrl-h すると、
cympfh% Hello
_
こうなる. ここで _ がカーソル. ちなみに zle reset-prompt を呼ぶとプロンプトを作り直してくれるのだが、割と使う.
cd-up() {
    cd ..
    zle reset-prompt
}
zle -N cd-up
bindkey "^G^U" cd-up
cd-old() {
    cd -
    zle reset-prompt
}
zle -N cd-old
bindkey "^G^O" cd-old
cd-home() {
    cd
    zle reset-prompt
}
zle -N cd-home
bindkey "^G^H" cd-home
cd-recent() {
    cd $(cat ~/.zsh_pwd_history | tac | peco)
    zle reset-prompt
}
zle -N cd-recent
bindkey "^G^R" cd-recent大体最初に示した bindkey の使い方の通り. 実際に呼びたい関数を定義して bindkey でキーマッピングを設定するだけ. 最後の cd-recent は最近行ったことのあるディレクトリを ~/.zsh_pwd_history に 別な設定 で書き出してるので、 ここから行き先を peco で選んで移動させるコマンド.
どれもそれなりに使ってるけど、一番使ってるのは明らかに cd-recent. 最近の履歴を使う系は基本的に便利.
call-history() {
    BUFFER=$(history -n 1 | tac | peco --query "$BUFFER")
    CURSOR=$#BUFFER
    zle reset-prompt
}
zle -N call-history
bindkey "^R" call-historyhistory コマンドはコマンド入力履歴を出力してくれるのは便利だけど、 どうせならそこからインタラクティブに選んで、それがターミナルに入力された状態にしたい.
ターミナルの入力をいじるのが目的なのに、そのためにコマンド入力をするのは不自然なので bindkey に仕込んだ. すでにコマンド入力されてる文字列があれば、予めその文字列で history をフィルタする. これは peco の --query に指定すれば実現できる.
例えば、コマンドの頭だけ書いててオプション以降が思い出せない、みたいなときにその場で Ctrl-r を押すとそれっぽいのがズラっと出てくるので、気をつけて選べば良い. 選択した時点で実行させないのは、最後に念のために確認したり、ちょっとだけ変えたいときがあるので.
$BUFFER と $CURSOR という2つの変数を使っていて、 察しの通り、$BUFFER にはその時点でコマンド入力されている文字列が入っているし、代入すればセットできる. 長さの異なる文字列をセットしてもカーソルは変わらずそこにあるので、$CURSOR に $BUFFER の長さをセットすることでカーソルを末尾に持っていっておく.
これもめちゃくちゃ使ってる. 履歴使う系は基本全部便利.