これは "今年書いて良かった 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-history
history
コマンドはコマンド入力履歴を出力してくれるのは便利だけど、 どうせならそこからインタラクティブに選んで、それがターミナルに入力された状態にしたい.
ターミナルの入力をいじるのが目的なのに、そのためにコマンド入力をするのは不自然なので bindkey
に仕込んだ. すでにコマンド入力されてる文字列があれば、予めその文字列で history
をフィルタする. これは peco
の --query
に指定すれば実現できる.
例えば、コマンドの頭だけ書いててオプション以降が思い出せない、みたいなときにその場で Ctrl-r
を押すとそれっぽいのがズラっと出てくるので、気をつけて選べば良い. 選択した時点で実行させないのは、最後に念のために確認したり、ちょっとだけ変えたいときがあるので.
$BUFFER
と $CURSOR
という2つの変数を使っていて、 察しの通り、$BUFFER
にはその時点でコマンド入力されている文字列が入っているし、代入すればセットできる. 長さの異なる文字列をセットしてもカーソルは変わらずそこにあるので、$CURSOR
に $BUFFER
の長さをセットすることでカーソルを末尾に持っていっておく.
これもめちゃくちゃ使ってる. 履歴使う系は基本全部便利.